D3.jsで分割したCSVファイルを読み取る方法とアニメーションをgifで紹介!

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている[りく](https://qiita.com/rikukaikuu)です。

[前回](https://qiita.com/POSSE/items/b37aa04665aeb9850664)に続き、D3.jsでできることの探求をしていきます。

していることは前回と同じですが、できることを増やすためにコードを書き変えています。
というのも、前回のは

- 一定数以上のデータがあると全て表示されず、データが見切れてしまう
- データを入れるには**dataset**に入れる必要があるため、数字を入れる専用のファイルが欲しい
- ~~前のやり方だと頭に入らなかった~~

といった理由から新たに書き直しました。

#CSVファイルを読み取る

```html:graph.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>改良版</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
  </head>

  <body>
    <script>
      var dataset = d3.csv("data.csv", function(error, data) {
        console.log(data);
      });

      var w = 500; 
      var h = 500; 
      var padding = 30; 

      var svg = d3
        .select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h);

      var xScale = d3
        .scaleBand()
        .rangeRound([padding, w - padding])
        .padding(0.1)
        .domain(
          dataset.map(function(d) {
            return d.name;
          })
        );

      var yScale = d3
        .scaleLinear()
        .domain([
          0,
          d3.max(dataset, function(d) {
            return d.value;
          })
        ])
        .range([h - padding, padding]);

      svg
        .append("g")
        .attr("transform", "translate(" + 0 + "," + (h - padding) + ")")
        .call(d3.axisBottom(xScale));

      svg
        .append("g")
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", function(d) {
          return xScale(d.name);
        })
        .attr("y", function(d) {
          return h;
        })
        .attr("width", xScale.bandwidth())
        .attr("height", function(d) {
          return -30;
        }) // -30 何回かやってこれが1番合ってた
        .transition()
        .duration(500)
        .delay(function(d, i) {
          return i * 50;
        })
        .attr("y", function(d) {
          return yScale(d.value);
        })
        .attr("height", function(d) {
          return h - padding - yScale(d.value);
        })
        .attr("style", "fill:red");
    </script>
  </body>
</html>

```

```csv:data.csv
name,value
A,5
B,6
C,8
D,1
E,2
F,6
G,8
H,6
I,10
J,9
K,11
L,21

```
完成したのが以下の通りです。

![ezgif.com-video-to-gif (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369905/5cc219da-e91c-a9c2-d113-6b93bb4e9040.gif)

#上のアニメーションをさせるためにいろいろ繰り返した結果できた産物達
上記のコードにたどり着くまでにいろいろコードを試してみたのですが、なかなか(個人的に)おもしろいムーブをしたので、いくつか紹介します。

##色が変わっていくアニメーション

```javascript:graph.html
     svg.append("g")
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", function(d) {
          return xScale(d.name);
        })
        .attr("y", function(d) {
          return yScale(d.value);
        })
        .attr("width", xScale.bandwidth())
        .attr("height", function(d) {
          return h - padding - yScale(d.value);
        }) //ここからアニメーション
        .transition()
        .duration(500)
        .delay(function(d, i) {
          return i * 50;
        })
        .attr("style", "fill:red");
```

すると、こんなことになります。
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369905/1836bf8a-7c29-dc0f-e474-fc1c2094b4ce.gif)

意図してない動きだったけどこれはこれでアリやな!

##グラフが迫ってくるアニメーション

アニメーションのコードを上にするだけで(処理の順番が変わるので当たり前ですが)かなり変わります。

```javascript:graph.html
      svg.append("g")
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .transition() //ここからアニメーション
        .duration(500)
        .delay(function(d, i) {
          return i * 50;
        })
        .attr("style", "fill:red")
        .attr("x", function(d) {
          return xScale(d.name);
        })
        .attr("y", function(d) {
          return yScale(d.value);
        })
        .attr("width", xScale.bandwidth())
        .attr("height", function(d) {
          return h - padding - yScale(d.value);
        });
```
![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369905/8a3c50a7-25b9-2256-91de-8972a8695ea6.gif)
こうすると、遠くからグラフが攻めてくるみたいでかっこいいですね!

##グラフが降ってくるアニメーション

```javascript:graph.html
      svg
        .append("g")
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", function(d) {
          return xScale(d.name);
        })
        .attr("y", function(d) {
          return yScale(d.value);
        })
        .attr("width", xScale.bandwidth())
        .attr("height", function(d) {
          return h - padding - yScale(d.value);
        })
        .transition()
        .duration(500)
        .delay(function(d, i) {
          return i * 50;
        })
        .attr("style", "fill:red");
```
![ezgif.com-video-to-gif (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369905/c5820498-72d5-865b-9c98-1f51bb272e04.gif)

これは、上からグラフが降ってくるようなアニメーションをするコードです。
棒グラフが地面に着地した演出ができあがります。

##落ちて色が変化するアニメーション

```javascript:graph.html

      svg
        .append("g")
        .selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", function(d) {
          return xScale(d.name);
        })
        .attr("y", 0)
        .attr("width", xScale.bandwidth())
        .attr("height", 100)
        .transition()
        .duration(500)
        .delay(function(d, i) {
          return i * 50;
        })
        .attr("y", function(d) {
          return yScale(d.value);
        })
        .attr("height", function(d) {
          return h - padding - yScale(d.value);
        })
        .attr("style", "fill:red");
```
![ezgif.com-video-to-gif (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369905/3eadf31b-dc56-b2c0-c406-989b22cc8354.gif)

これは、先ほどのように上からグラフが降ってくるのですが、降る前に無色(黒)の状態で待機していて、アニメーションが開始したら色がついて降ってくるものになりました。
うまくできれば、つららが落ちてくるような演出とかもできそう。


#まとめ
こんなのが意図しなくてもできるんだからいろいろ試してみるもんですね～
~~意図してできたらいいんですけど~~