D3.js로 꺾은선형 차트를 간단하게 그립니다.

16974 단어 d3.js
tumblr 의 Activity를 보고 있고, 이런 일은, D3.js 사용하면 할 수 있을까라고 생각해 시험해 보았습니다.

tumblr 활동의 꺾은선형 차트:


원이나 막대 그래프는 심플한 샘플이 있습니다만, 꺾은 선 그래프는 부드럽게 중후장대한 샘플 밖에 보여지지 않았기 때문에, 연습을 겸해.

D3는 데이터 세트의 방법이 독특하고 버릇을 잡으면 재미있을 것 같습니다.

하고 싶은 일



Activity는, 과거 1일 단위의 Note수인 것 같습니다만, 직접 소스를 보면, 일간의 Note 수를 그대로 배열로 하고 있는 것 같습니다.

이번은 마찬가지로 과거의 Note 수 같은 데이터를 꺾은 선 그래프로 해 보겠습니다.

샘플



파일에 복사하여 저장하고 브라우저에서 호출하면 작동합니다.
Chrome에서 확인했습니다.

linear_path.html
<!DOCTYPE html>
<meta charset="utf-8">
<body>


<script src="http://d3js.org/d3.v3.js"></script>
<script>

// この10個のデータを折れ線グラフにする
var dataset =[ 2,0,0,0,0,0,0,0,1,1 ];

// 50x50のsvg領域を作る
var w = 50;
var h = 50;
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

// datasetを{x,y}の座標の配列に変換する。
// X座標は、領域全体を個数で割って全体を使えるようにする。
// 原点が左上なので、Y座標は最大値から引き算する
// それぞれ2ずらしているのは、0地点の場合に線が欠けるため。
var  pathinfo = [];
var b_x = w / dataset.length;
for (var i=0; i<dataset.length; i++) {
  pathinfo.push({x:b_x*i+2, y:((h-2) - dataset[i]*10) });
}

// 座標データから折れ線グラフ用のコマンドを作るための関数を用意
var d3line = d3.svg.line()
  .x(function(d){return d.x;})
  .y(function(d){return d.y;})
  .interpolate("linear"); // エッジがシャープな折れ線を指定。
 // 参考 https://www.dashingd3js.com/svg-paths-and-d3js

// 実際に線を引く。
svg.append("path")
  .attr("d", d3line(pathinfo)) // さきほどの関数に座標の配列を引数で渡す
  .style("stroke-width", 2) // 線の太さを決める
  .style("stroke", "steelblue") // 色を決める
  .style("fill", "none");

</script>

</body>
</html>

실행 예



이런 느낌이 듭니다.

[ 2,0,0,0,0,0,0,0,1,1 ]의 꺾은선형 차트:


서버로부터는 단순한 데이터를 클라이언트에 건네주고, 클라이언트로 작은 그래프를 생성하도록(듯이) 하면, 상당히 보기 좋게 좋을지도 모르겠네요. 서버에 부하가 걸리지 않습니다.

보충 - d3.scale을 사용해 보았습니다.



d3.scale을 사용하면 {x, y}의 배열을 만들거나 for로 루프를 돌려 계산할 필요가 없기 때문에 전망이 좋아지는 것을 알았으므로 추가.

linear_path2.html
<!DOCTYPE html>
<meta charset="utf-8">
<body>

<script src="http://d3js.org/d3.v3.js"></script>
<script>

// この10個のデータを折れ線グラフにする
var dataset =[ 2,0,0,0,0,0,0,0,1,1 ];

// 50x50のsvg領域を作る
var w = 50;
var h = 50;
var margin = 2; // 描画を内側に少し寄せるためのマージン
var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

// 配列内の値に差がなさすぎると、グラフの見た目に違和感があるので、
// 最低でも5ポイント差がつくようにする
var ymin = d3.min(dataset);
var ymax = d3.max(dataset);
if ((ymax - ymin) < 5) {
  ymax += 5 - (ymax - ymin);
}

// d3.scaleを設定する。
// x座標は、0からdatasetの配列の数(ここでは10個)までを、0からwidthまで
//(正確にはmargin分内側に寄せて、marginからw-marginまで)にマッピングする
// 線形(linear)のマッピングなので、xscale(0)は2に、xscale(10)は48(w-margin)になる。
var xscale = d3.scale.linear().domain([0,dataset.length]).range([margin,w-margin]);

// y座標は、配列内の最低値から最大値までを、h-marginからmarginまでにマッピングする
// svg座標系がyについては逆になっているので、0からheightではなくて、heightから0とする。
// yscale(0)は48(h-margin)に、yscale(5)は2になる。(上の計算でymax=5となっているため)
var yscale = d3.scale.linear().domain([ymin, ymax]).range([h-margin,margin]);

// 座標データから折れ線グラフ用のコマンドを作るための関数を用意
var d3line = d3.svg.line()
  .x(function(d,i){return xscale(i);}) // iには配列のindexが一つずつ入る
  .y(function(d){return yscale(d);}) // dは配列の値が一つずつ入る
  .interpolate("linear"); // エッジがシャープな折れ線を指定。
 // 参考 https://www.dashingd3js.com/svg-paths-and-d3js

// 実際に線を引く。
svg.append("path")
  .attr("d", d3line(dataset)) // さきほどの関数に座標の配列を引数で渡す
  .style("stroke-width", 2) // 線の太さを決める
  .style("stroke", "steelblue") // 色を決める
  .style("fill", "none");

</script>

</body>
</html>

결과는 위 그래프와 동일합니다. scale을 기억하면 편해지네요.
D3.js는 for문을 사용하지 않는 프로그래밍을 할 수 있으므로, 데이터를 for문으로 가공해야 할 필요가 없어지면, 뭔가 API 없는지 조사하는 것이 길군요.

좋은 웹페이지 즐겨찾기