transitionを利用したsvgオブジェクトの「連続的」変化2
前回、transitionを利用して画面上を円が駆けるアニメーションを作りました。
その際、先に座標データを連想配列として準備しておきました。
円の中心座標が、次々にその座標データを読み込んで移動しました。
今回は、ちょっと違う切り口で円が駆けるアニメーションを作成します。
まずは、前回までと同様に、SVGオブジェクトを準備します。
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"> var svg = d3.select("body").select("div") .append("svg") .attr("width",600) .attr("height",450) .style("background-color", "black"); </script>
でも、今回は、最初に円を描きません。
次に座標データを連想配列で作成します。
var svgwidth = 600; var svgheight = 450; for (var i = 0; i < 200; i++){ if (i === 0) { var cx = (svgwidth / 2); var cy = (svgheight / 2); } else { var cx = arr[(i-1)].x + ((Math.random() * 60) - 30); var cy = arr[(i-1)].y + ((Math.random() * 60) - 30); } arr.push(new Object({x: cx, y: cy})); }
配列の最初の要素は、SVGオブジェクトの中心にします。今回の例では、Math.random()を利用して、あと199個要素を生成し、配列に保存しています。
では、円を描いてみましょう。今回は、svgという変数の下に、data()とenter()を利用して配列データを読み込ませます。その下に、append("circle")を置いたので、200個の円が画面上に描かれます。アニメーションとして一つずつ出現してもらいたいので、rを0にしてとりあえず見えないようにしました。
(追記:投稿時はopacityを0にしていましたが、rを0にすると描画の負担を劇的に減らせるので変更しました。)
svg .selectAll("circle") .data(arr) .enter() .append("circle") .style("fill", "blue") .style("stroke", "lightblue") .attr("r", "0px");
描いた円が順番に現れて、ぼんやり消えていくようにします。
transition()の出番です。
svg .transition() .delay(function(d,i) { return i * 100; }) .duration(100) .attr("r", "20px") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; });
ここまでのコードで画面に円が次々に出現します。delayの設定では、データの順序をiで読んでいます。
なので、100msずつ出現タイミングがずれます。また、中心座標をtransitionの下にチェインさせています。どうやらtransitionの前は(0,0)の位置に200個の見えない円が描かれているようです。
svg .selectAll("circle") .transition() .delay(function(d,i) { return (100 + (i * 100)); }) .duration(500) .style("opacity", 0) .remove();
こちらは円がぼんやり消えるためのコードです。durationで500としたので、500msかけて円が透明になります。透明に成りきったところでremoveが実行されて円がHTML上から消滅します。
ここまでをまとめると以下のようになります。startボタンを押してみてください。
円がぼんやりと消えることで移動の軌跡が分かるかと思います。