目盛りの作成
ここでは、グラフの表示に欠かせない目盛りを作成します。まず、x座標の目盛りを作成します。
まず、スケール関数を定義した後に、そのスケールを利用して目盛りを定義します。
//スケール関数を作成(既に作成している)
var xScale = d3.scaleLinear()
.domain([0, max_x])
.range([padding, w - padding * 2]);
var yScale = d3.scaleLinear()
.domain([0, max_y])
.range([h - padding, padding]);
//新しくx座標の目盛りを定義
var xAxis = d3.axisBottom(xScale);
そして、最終行に以下を記述します。gタグは、目盛りをグループとして保存しておくためのタグです。
//x座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.call(xAxis);
このままですと、目盛りが上にあるのは変なので、transformを使って下に移動します。
transformは一見難しく見えますが、単純にtransform(x, y)で座標を指定しているだけです。
また、あとで使うので、この目盛りにaxisというクラス名を設定しておきましょう。
//x座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding) + ")") //目盛りを移動
.call(xAxis);
完全なコードは以下です。
<script type="text/javascript">
var w = 500;
var h = 300;
var padding = 30;
var dataset = [
[25, 50], [250, 100], [110, 80], [175, 240], [450, 280],
[130, 58], [190, 97], [154, 230], [60, 20], [171, 60]
];
//x座標用配列の値の最大値
var max_x = d3.max(dataset, function(d){
return d[0];
});
//y座標用配列の値の最大値
var max_y = d3.max(dataset, function(d){
return d[1];
});
//スケール関数を作成
var xScale = d3.scaleLinear()
.domain([0, max_x])
.range([padding, w - padding * 2]);
var yScale = d3.scaleLinear()
.domain([0, max_y])
.range([h - padding, padding]);
//x座標の目盛りを定義
var xAxis = d3.axisBottom(xScale);
//SVG要素を作成
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]); //二次元配列の一つ目の値
})
.attr("cy", function(d) {
return yScale(d[1]); //二次元配列の二つ目の値
})
.attr("r", function(d){
return d[1]/10;
}); //半径
//ラベルを作成
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
//半径(d[1]/10)+10ピクセル分だけ下に下げる
return yScale(d[1]) + d[1] / 10 + 10;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "blue");
//x座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")") //目盛りを移動
.call(xAxis);
</script>
CSSで目盛りの見た目を調整する
かなり目盛りらしくなってきましたが、実は目盛りも全てSVGで描画されているので、CSSを使えば様々なデザインが可能です。以下のCSSを宣言してください。
.axis path,
.axis line {
fill: none;
stroke: #556B2F;
shape-rendering: crispEdges; /*形をシャープに描画*/
}
.axis text {
font-family: sans-serif;
font-size: 11px;
fill: #556B2F;
}
以下のようになります。
また、目盛りを定義する際に.ticks()を記載すると、目盛りの数を変更できます。この場合、.ticks(5)と宣言した場合は、d3は目盛りの数を5前後で一番適切な数に決めてくれます。
/x座標の目盛りを定義
var xAxis = d3.axisBottom(xScale)
.ticks(5);
以下のようになります。
最後に、x座標の目盛りのコードの下に、y座標のコードを追加しましょう。
//x座標の目盛りを定義
var xAxis = d3.axisBottom(xScale)
.ticks(5);
//y座標の目盛りを定義
var yAxis = d3.axisLeft(yScale)
.ticks(5);
//x座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding) + ")") //目盛りを移動
.call(xAxis);
//y座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.attr("class", "y axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
以下のようになります。
目盛りの単位を%に変更
目盛りの単位は自由に表示を変更することができます。ここでは、%で表示してみましょう。
//x座標の目盛りを定義
var xAxis = d3.axisBottom(xScale)
.ticks(5)
.tickFormat(d3.format(".1%"));
以下のようになります。
完全なコードは以下です。
<script type="text/javascript">
var w = 500;
var h = 300;
var padding = 30;
var dataset = [
[25, 50], [250, 100], [110, 80], [175, 240], [450, 280],
[130, 58], [190, 97], [154, 230], [60, 20], [171, 60]
];
//x座標用配列の値の最大値
var max_x = d3.max(dataset, function(d){
return d[0];
});
//y座標用配列の値の最大値
var max_y = d3.max(dataset, function(d){
return d[1];
});
//スケール関数を作成
var xScale = d3.scaleLinear()
.domain([0, max_x])
.range([padding, w - padding * 2]);
var yScale = d3.scaleLinear()
.domain([0, max_y])
.range([h - padding, padding]);
//x座標の目盛りを定義
var xAxis = d3.axisBottom(xScale)
.ticks(5)
.tickFormat(d3.format(".1%"));
//y座標の目盛りを定義
var yAxis = d3.axisLeft(yScale)
.ticks(5);
//SVG要素を作成
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d[0]); //二次元配列の一つ目の値
})
.attr("cy", function(d) {
return yScale(d[1]); //二次元配列の二つ目の値
})
.attr("r", function(d){
return d[1]/10;
}); //半径
//ラベルを作成
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) {
return d[0] + "," + d[1];
})
.attr("x", function(d) {
return xScale(d[0]);
})
.attr("y", function(d) {
//半径(d[1]/10)+10ピクセル分だけ下に下げる
return yScale(d[1]) + d[1] / 10 + 10;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "blue");
//x座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding) + ")") //目盛りを移動
.call(xAxis);
//y座標の目盛りを作成
svg.append("g") //gはグループ用のsvgタグ
.attr("class", "y axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
</script>
その他、様々な表記がありますが、以下のサイトにわかりやすくまとめられていたので引用します。
https://qiita.com/tkosuga@github/items/ec3a36d5bcd26c822304