モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

D3.js / v5 の基本的な使い方

モーダルを閉じる

ステッカーを選択してください

お支払い手続きへ
モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

作成日作成日
2018/09/16
最終更新最終更新
2020/12/23
記事区分記事区分
一般公開

目次

    C/C++やアルゴリズムに注目し、実践的な知識を発信しています!

    データをもとにして DOM を操作する D3.js (Data-Driven Documents) の基本的な使い方を記載します。特にバージョンは v5 を対象とします。

    Hello world

    HTTP サーバ

    外部からデータを読み込むために CORSを考慮する必要があります。D3.js の動作検証時には簡単な HTTP サーバを立てる必要があります。Python を利用する場合は以下のようにします。

    python2 -m SimpleHTTPServer 8888
    python3 -m http.server 8888
    

    http://localhost:8888/path/to/sample.html で動作確認できるようになります。

    インストール

    CDN を利用する場合は以下のいずれかを指定します。

    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://d3js.org/d3.v5.js"></script>
    

    GitHub からリリース zip ファイルをダウンロードして利用することもできます。

    npm/yarn 経由でインストールすることもできます。

    npm view d3 versions --json
    

    動作確認

    CSS セレクタで要素を指定します。jQuery 等と同様です。data に応じて DOM の font-size を変更しています。jQuery 等と同様に D3 は DOM ツリーが完成した後に実行する必要があります。例えば以下のように body の最後に script を記述します。

    sample.html

    <html>
    <head>
      <script src="https://d3js.org/d3.v5.min.js"></script>
    </head>
    <body style="background:#fafafa">
      <p>1</p>
      <p>2</p>
      <p>3</p>
      <p>4</p>
      <p>5</p>
      <script>
       d3.selectAll("p")
         .data([4, 8, 15, 16, 23])
         .style("font-size", function(d) { return d + "px"; });
      </script>
    </body>
    </html>
    

    新規データによる既存 DOM の更新

    • 既存 DOM の要素を新規データで更新するためには単純に select して処理すればよいです。
    • 既存 DOM の要素数が新規データ数よりも少ない場合は enter().append() で追加できます。
    • 既存 DOM の要素数が新規データ数よりも多い場合は exit().remove() で削除できます。

    既存 DOM の 999 を新規データで更新した後に、新規 DOM の追加またはデータ数よりも多い既存 DOM の削除を行っています。

    <html>
    <head>
      <script src="https://d3js.org/d3.v5.min.js"></script>
    </head>
    <body style="background:#fafafa">
      <div id="myid1">
        <p>999</p>
      </div>
      <div id="myid2">
        <p>999</p>
        <p>999</p>
        <p>999</p>
        <p>999</p>
      </div>
      <script>
       /////////////////////////////////
       // Update
       var p1 = d3.select("div#myid1")
                 .selectAll("p")
                 .data([4, 8])
                 .text(function(d) { return "updated: " + d; });
       // Enter
       p1.enter().append("p")
         .text(function(d) { return "added: " + d; });
       // Exit
       p1.exit().remove();
    
       /////////////////////////////////
       // Update
       var p2 = d3.select("div#myid2")
                 .selectAll("p")
                 .data([4, 8])
                 .text(function(d) { return "updated: " + d; });
       // Enter
       p2.enter().append("p")
         .text(function(d) { return "added: " + d; });
       // Exit
       p2.exit().remove();
      </script>
    </body>
    </html>
    

    遷移

    1000ミリ秒 delay 待機してから、1000ミリ秒 duration 期間で font-size 100px に遷移します。

    <html>
    <head>
      <script src="https://d3js.org/d3.v5.min.js"></script>
    </head>
    <body style="background:#fafafa">
      <p>hi</p>
      <script>
       d3.select("p")
         .transition()
         .duration(1000)
         .delay(1000)
         .style("font-size", "100px");
      </script>
    </body>
    </html>
    

    遷移前

    遷移後

    属性値の変更

    CSS 値ではなく HTML の属性値を変更する場合は attr を利用します。

    d3.select("p")
      .attr("class", "myclass");
    

    TSV から折れ線グラフを生成して描画

    D3 v4 のサンプルコードを v5 用に変換してあります。D3 を利用すると細かな制御が可能ですが、複雑なことをせずに表示するだけであれば plotly.js 等を利用すると簡単です。

    <html>
    <head>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <style>
     .axis--x path {
       display: none;
     }
     .line {
       fill: none;
       stroke: steelblue;
       stroke-width: 1.5px;
     }
    </style>
    </head>
    <body style="background:#fafafa">
    
    <!-- 以下の svg タグを D3 から操作します -->
    <svg width="960" height="500"></svg>
    
    <script>
    
    // svg タグ
    var svg = d3.select("svg");
    
    // グラフ本体のサイズを計算
    var margin = {top: 20, right: 80, bottom: 30, left: 50};
    var width = svg.attr("width") - margin.left - margin.right;
    var height = svg.attr("height") - margin.top - margin.bottom;
    
    // svg タグ内で利用する div のようなコンテナ要素 'g' https://developer.mozilla.org/ja/docs/Web/SVG/Element/g
    // グラフ本体 g を移動させます https://developer.mozilla.org/ja/docs/Web/SVG/Attribute/transform
    var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    // ユーティリティ関数を定義 https://github.com/d3/d3-time-format
    // Date を返します
    var parseTime = d3.timeParse("%Y%m%d");
    //var parseTime = d3.timeParse("%s"); // タイムスタンプの場合
    
    // 入力データの区間 domain[from, to] を
    // グラフ上の区間 range[from, to] に変換 scale するための関数を定義
    // https://github.com/d3/d3-scale/blob/master/README.md
    var xx = d3.scaleTime().range([0, width]);
    var yy = d3.scaleLinear().range([height, 0]);
    // 折れ線の色を変えるために range を `d3.schemeCategory10` に指定
    // https://github.com/d3/d3-scale-chromatic/blob/master/README.md#schemeCategory10
    var zz = d3.scaleOrdinal(d3.schemeCategory10);
    
    // データから折れ線を生成するための関数を定義
    // [{ date: "20111001", temperature: 63.4 }]
    // という形式の配列の要素をグラフ上の点に変換する .x() と .y() を設定
    // https://github.com/d3/d3-shape/blob/master/README.md
    var line = d3.line()
        .curve(d3.curveBasis)
        .x(function(d) { return xx(d.date); })
        .y(function(d) { return yy(d.temperature); });
    
    // TSV を読み込んで処理
    // (非同期処理のプロミスが利用されています )
    d3.tsv("http://localhost:8888/data.tsv").then(function(data) {
    
      // TSV を利用しやすい形式に変換
      // [{"date":"20111001", "New York":"63.4", "San Francisco":"62.7", "Austin":"72.2"}]
      var cities = data.columns.slice(1).map(function(cityName) {
        return {
          id: cityName,
          values: data.map(function(d) {
            return {date: parseTime(d.date), temperature: d[cityName]};
          })
        };
      });
    
      // X 軸の入力データ幅を設定
      // https://github.com/d3/d3-array/blob/master/README.md#extent
      xx.domain(d3.extent(data, function(d) { return parseTime(d.date); }));
    
      // Y 軸の入力データ幅を設定
      yy.domain([
        d3.min(cities, function(c) { return d3.min(c.values, function(d) { return d.temperature; }); }),
        d3.max(cities, function(c) { return d3.max(c.values, function(d) { return d.temperature; }); })
      ]);
    
      // 複数のグラフ (Z 軸の入力は cityName とします)
      zz.domain(cities.map(function(c) { return c.id; }));
    
      // 横軸のラベルを追加
      g.append("g")
          .attr("class", "axis axis--x")
          .attr("transform", "translate(0," + height + ")")
          .call(d3.axisBottom(xx));
    
      // 縦軸のラベルを追加
      // https://developer.mozilla.org/ja/docs/Web/SVG/Element/text
      g.append("g")
          .attr("class", "axis axis--y")
          .call(d3.axisLeft(yy))
        .append("text")
          .attr("transform", "rotate(-90)")
          .attr("y", 15) // グラフから 15px 離します
          .attr("fill", "#000")
          .text("Temperature, ºF");
    
      // TSV から加工した cities データの種類分だけ g を追加
      var city = g.selectAll(".city")
        .data(cities)
        .enter().append("g")
          .attr("class", "city");
    
      // 折れ線として SVG の path 要素を追加 https://developer.mozilla.org/ja/docs/Web/SVG/Element/path
      city.append("path")
          .attr("class", "line")
          .attr("d", function(d) { return line(d.values); })
          .style("stroke", function(d) { return zz(d.id); });
    
      // 折れ線のラベルとして SVG の text 要素を追加 https://developer.mozilla.org/ja/docs/Web/SVG/Element/text
      city.append("text")
          .datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; }) // 各 city の最後の要素
          .attr("transform", function(d) { return "translate(" + xx(d.value.date) + "," + yy(d.value.temperature) + ")"; })
          .attr("x", 5) // 5px
          .style("font", "10px sans-serif")
          .text(function(d) { return d.id; });
    });
    </script>
    </body>
    </html>
    

    data.tsv

    date  New York  San Francisco  Austin
    20111001  63.4  62.7  72.2
    20111002  58.0  59.9  67.7
    20111003  53.3  59.1  69.4
    ...
    
    20120928  68.7  52.6  77.2
    20120929  62.5  53.9  75.2
    20120930  62.3  55.1  71.9
    
    Likeボタン(off)0
    詳細設定を開く/閉じる
    アカウント プロフィール画像

    C/C++やアルゴリズムに注目し、実践的な知識を発信しています!

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    >>さらに詳しくステッカーを贈る
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      ログインする

      関連記事