読者です 読者をやめる 読者になる 読者になる

おまじないの綴り方

spelling of a logical spell

d3.jsで棒グラフを書くときのサンプル

目標

下のような棒グラフをd3.jsを使って書く f:id:miyatsuki_yatsuki:20170226043919p:plain:w600

環境

d3.js 4.6.0

特記事項

全般

  • highcharts.jsなどのライブラリと比較すると考え方がかなり違うので、移行の際は注意
    • グラフを描画するためのライブラリではない
    • いい感じの見た目で描画されるようにDOMを置いてくれるライブラリというイメージ
    • そのため見た目のカスタマイズ時はAPIだけでなくCSSをいじって解決することも可能

バージョン

  • d3.jsがバージョン3と4でAPIがかなり変わっているので、調べるときはバージョンに注意が必要
  • 例えば、以下の記述はv4では使えない(が、割と見かける)
    //エラーも出ない
    .attr({
        x : function(d, i) { return i}
        y : function(d){ return d },
    }); 

  
  //こちらはエラーは出る
  d3.scale.linear()

コード

<html>
<head>
  <script type="text/javascript" src="d3.js"></script>
</head>

<body>
  <!-- グラフを描画するためのsvg要素を作っておく -->
  <svg id="bar" width="500" height="300"></svg>

  <script type="text/javascript">
  width = 500;
  height = 300;
  elementName = "#bar" //作っておいたsvg要素の名前

  var dataSet = []; //棒グラフの各項目の値
  var dataLabel = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]; //棒グラフの各項目の名前

  for (var i = 0; i < 10; i++)
  {
    dataSet.push(Math.random())
  }

  //グラフの各値をいい感じのwidthにするための変換関数
  var x = d3.scaleLinear() //配列の中身が数字 かつ 線形なグラフのとき
  .domain([0, 1]) //グラフがとりうる値の範囲
  .rangeRound([20, width-10])
  //実際の長さとしての範囲をいくつからいくつにするか。マージンをどの程度取りたいかの指定として使える。

  //グラフのラベル数にもとづいて、項目間の幅をいい感じにするための変換関数
  var y = d3
  .scaleBand() //配列の中身がラベルのとき
  .domain(dataLabel) //配列をそのまま渡す
  .rangeRound([20, height]); //実際の長さとしての範囲をいくつからいくつにするか

  //xとyは軸の描画でも使う

  //グラフ用のsvg要素に棒グラフの「棒(rect)」を追加する
  d3
  .select(elementName) // svg要素を指定
  .selectAll('rect') // その中のrect要素を抽出(なければ空オブジェクトが返ってくる)
  .data(dataSet) // 描画元のデータを指定
  .enter() // selectAllで足りない分の要素を確保する
  .append('rect'); //確保した要素にrectとして追加する

  //棒グラフの「棒」の部分の描画
  d3.select(elementName).selectAll('rect') //svg要素の中のrect要素をすべて選択(さっき作ったもの)
  .attr("class", "bar") //棒グラフであることを明示(必須ではない)
  .attr("x", function(d){return x(0)})
  //各値のx座標を指定。左端にしたいので0にする。
  //ここで、x関数をかませることで、マージンを考慮した「左端」が指定できる
  .attr("y", function(d, i){return y(dataLabel[i])})
  //各要素のy座標をy関数を使って指定。y関数はdataLabel内の要素に紐付いているので、y(dataLabel)の形式になる。
  //iはdataSetの何番目の要素を参照しているかが入る
  .attr("height", 15)
  //各棒の縦の長さ(今回は棒の幅)
  .attr("width", function(d){return x(d)})
  //各棒の横の長さ(今回は棒の長さ)
  //dはdataSetの値そのものが入る。x関数を噛ませて長さを指定。
  .attr("fill", "#6fbadd")
  //棒の色

  //棒グラフのx軸の描画
  d3.select(elementName) //グラフ用のsvg要素を持ってくる
  .append("g") //軸描画用の要素を追加(gという名前じゃないと動かない)
  .attr("class", "axis axis--x") //x軸用の要素を追加
  .attr("transform", "translate(0, 20)") //(0,20)の位置を起点として描画
  .call(d3.axisTop(x)); //上に軸が出るように設定

 //棒グラフのy軸の描画
  d3.select(elementName) //グラフ用のsvg要素を持ってくる
  .append("g") //軸描画用の要素を追加(gという名前じゃないと動かない)
  .attr("class", "axis axis--y") //y軸用の要素を追加
  .attr("transform", "translate(20, 0)") //(20,0)の位置を起点として描画
  .call(d3.axisLeft(y)); //左に軸が出るように設定

</script>

</body>

</html>