前回のエントリー!では、とりあえず表示できるところまでやりました。今回はもう少しD3らしい形にしていきます。
d3.scale, selection.data()
var minHeight = d3.min(member, function(d){return d.height}); var maxHeight = d3.max(member, function(d){return d.height}); var hScale = d3.scale.linear() .domain([minHeight, maxHeight]) .range([h - offset, offset]);
入力領域はdomain、出力範囲はrangeで指定する。
ここではminHeightからmaxHeightの入力領域を、表示領域(svgのサイズ)の端からoffsetを引いたところからoffset分ずらしたもう一端まで等間隔に対応させる数値にします。
つまりhScale(にこ先輩の身長) = offset, hScale(エリーチカの身長) = h -offset
var graph = svg.selectAll(".select") .data(member); var group = graph.enter().append("g") .attr("class", "select"); var circles = group.append("circle") .attr("class", "select") .attr("cx", function(d, i) { return wScale(i); }) .attr("cy", r + offset) .attr("r", r) .attr("fill", function(d) { return "rgb(" + d.color + ")"; });
selection.data()でbindingしたデータが、最終行のfunctionに引数として渡されています。なお、第二引数は呼びだし順の数値です。
g, transform
svgのg要素は、htmlのdivのような感じです。transform属性を指定することによって、含まれる要素をまとめて動かしたり変形することが出来ます。
例えば<g transform="translate(10, 20)">とすると、右に10, 下に20移動します。
group.transition() .attr("transform", function(d, i) { return "translate(0," + (hScale(d.height) - r - offset) + ")"; });
transition
transformのソースに、selection.transition().attr()という形があります。
attr()で行われる変更にトランジション効果を設定しています。
selection.transition().
.delay(750).
.duration(750)
.attr("r", 30);
この場合は、delay, durationともに750msでrを30に変更します。
ソースとサンプル
ソース
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <style type="text/css"> circle { stroke: #333; stroke-width: 1.5px; } text { font: 10px sans-serif; } text.shadow { stroke: #fff; stroke-width: 3px; stroke-opacity: .8; } </style> </head> <body> <div id="graph"> <button>Run</button> </div> <script type="text/javascript" src="d3.v3.min.js"></script> <script>
d3.json("https://dl.dropbox.com/u/450748/d3.v3/mus.json", function(error, json) { var member = json.nodes; member.sort(function(a, b) { return b.height - a.height; }); var w = 720; var h = 540; var r = 30; var offset = r * 2; var svg = d3.select("#graph").append("svg") .attr("width", w) .attr("height", h); var graph = svg.selectAll(".select") .data(member); var wScale = d3.scale.linear() .domain([0, member.length - 1]) .range([offset, w - offset]); var minHeight = d3.min(member, function(d){return d.height}); var maxHeight = d3.max(member, function(d){return d.height}); var hScale = d3.scale.linear() .domain([minHeight, maxHeight]) .range([h - offset, offset]); var group = graph.enter().append("g") .attr("class", "select"); var circles = group.append("circle") .attr("class", "select") .attr("cx", function(d, i) { return wScale(i); }) .attr("cy", r + offset) .attr("r", r) .attr("fill", function(d) { return "rgb(" + d.color + ")"; }); var text = group.append("text") .attr("class", "select shadow") .attr("x", function(d, i) { return wScale(i); }) .attr("y", r + offset) .attr("text-anchor", "middle") .text(function(d) { return d.name; }); var textShadowed = group.append("text") .attr("class", "select") .attr("x", function(d, i) { return wScale(i); }) .attr("y", r + offset) .attr("text-anchor", "middle") .text(function(d) { return d.name; }); group.transition() .attr("transform", function(d, i) { return "translate(0," + (hScale(d.height) - r - offset) + ")"; }); var yAxis = d3.svg.axis() .scale(hScale) .orient("left"); svg.append("g") .attr("transform", "translate(" + r + ",0)") .attr("class", "select") .call(yAxis); // button click d3.select("#graph button").on("click", function() { var delayTime = 750; var durationTime = 750; // r circles.transition() .delay(delayTime) .duration(durationTime) .attr("r", function(d) { return d.B/2; }); var minB = d3.min(member, function(d){return d.B}); var maxB = d3.max(member, function(d){return d.B}); var wScaleByB = d3.scale.linear() .domain([minB, maxB]) .range([offset, w - offset]); group.transition() .delay(delayTime) .duration(durationTime) .attr("transform", function(d, i) { return "translate(" + (wScaleByB(d.B) - wScale(i)) + "," + (hScale(d.height) - r - offset) +")"; }); var xAxis = d3.svg.axis() .scale(wScaleByB) .orient("bottom"); var g = svg.append("g") .attr("class", "select") .attr("opacity", 0) .call(xAxis); g.transition() .duration(durationTime) .delay(delayTime) .attr("opacity", 1); }); });
</script> </body> </html>