jnobuyukiのブログ

研究していて困ったことやその解決に関するメモ。同じように困ったあなたのために。twitter ID: @j_nobuyuki

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ボタンを押してみてください。
円がぼんやりと消えることで移動の軌跡が分かるかと思います。