JavaScript で始めるデータ ビジュアライゼーション –D3 連携編–

バージョン 2

    ArcGIS API for JavaScript を用いてデータ ビジュアライゼーションの手法とそれを実現する機能についてご紹介していく「JavaScript で始めるデータ ビジュアライゼーション」シリーズの第6弾です。

    これまで紹介したサンプル コードとデモを確認したい方は GitHub リポジトリをご覧ください。

    第1弾から様々な表現手法をお伝えしてきましたが、今回は少し趣向を変えて、データ ビジュアライゼーションを強みとするオープンソース JavaScript ライブラリである D3.js との連携例をご紹介します。

     

     

    D3.js とは?

     

    データ ドリブン ドキュメント(Data Driven Document)を略して「D3」と呼ばれている通り、データを操作し、可視化することに優れたライブラリです。Web サイトや Web アプリで採用される 2D ベクター グラフィックの標準形式である SVG(Scalable Vector Graphics)の操作や数値計算、可視化までデータ ビジュアライゼーションの実現に必要な機能が揃っています。

    本稿ではこの D3 が ArcGIS API for JavaScript の地図アプリでどのように活躍するのか、その一例をご紹介していきたいと思います。

     

    まずは今回実装方法を紹介するサンプル アプリを触ってみてください。

    app.png

    ArcGIS API for JavaScript + D3

     

     

    SVG を CSS でスタイリング

    今回は震源地のデータが持つ震度情報をもとに数値分類を行い、震度に応じてポイントのシンボル表現を変えていきたいと思います。ArcGIS API for JavaScript で数値分類を行う場合、ClassBreaksRenderer クラスを使って実装するのが一般的ですが、今回このクラスは使いません。

     

    ArcGIS API for JavaScript で表現する地図上のグラフィックも D3 の操作対象である SVG 形式を採用しています。SVG は CSS でスタイルだけでなくアニメーションを定義することができるため、インタラクティブで美しいグラフィック表現を地図上で実現することができます。

    グラフィック(=フィーチャ)を作り出す SVG に対して data-classification という属性を与えて、数値に応じて値を振り分ける機能を実装してみます。

    以下のコードではそれを前提にあらかじめ CSS で数値分類に応じたグラフィックの表現を定義しています。

     

    /* 数値分類に応じた SVG のスタイリング */
    path[data-classification="0"] {
        fill: none;
        stroke: #0000ff;
        stroke-width: 10;
        stroke-opacity: 0.5;
        stroke-linecap: round;
        stroke-linejoin: round;
    }
    path[data-classification="1"] {
        fill: none;
        stroke: #5500ff;
        stroke-width: 15;
        stroke-opacity: 0.5;
        stroke-linecap: round;
        stroke-linejoin: round;
    }
    path[data-classification="2"] {
        fill: none;
        stroke: #ff00ff;
        stroke-width: 20;
        stroke-opacity: 0.5;
        stroke-linecap: round;
        stroke-linejoin: round;
    }
    path[data-classification="3"] {
        fill: none;
        stroke: #ff0080;
        stroke-width: 30;
        stroke-opacity: 0.5;
        stroke-linecap: round;
        stroke-linejoin: round;
    }
    path[data-classification="4"] {
        fill: none;
        stroke: #ff0000;
        stroke-width: 40;
        stroke-opacity: 0.5;
        stroke-linecap: round;
        stroke-linejoin: round;
    }
    

     

     

    数値分類を D3 で効率化

    先に定義した CSS を適用するために JavaScript 側で数値に応じた SVG に属性値(data-classification)を与えていきます。

    以下のコードの上側が D3 を使用した場合のコードです。

    数行のコードなので、これだけ?と思われるかもしれませんが、シンプルな連携例としてご理解ください。また、D3 を使わなかった場合の実装例と比較すると、どれだけ効率化されるのかを実感できます。

     

    早速ですが、以下のコードをご覧ください。D3 を使った場合ではたった数行で済むロジックも D3 を使わないと、数値分類の定義を配列でオブジェクトとして記述して、これをもとに条件分岐で属性値を与えていくといった実装になっており、コード量も多くなっています。

     

    ArcGIS API for JavaScript + D3

    // D3
    quantize = d3.scale.quantize().domain([10, 1500]).range(d3.range(5));
    
    // 避難所グラフィック描画時に実行
    on(hinanjo, "graphic-draw", function (evt) {
        var attrs = evt.graphic.attributes, Capacity = (attrs && attrs["収容人数"]) || undefined, range;
        // 収容人数に応じてレンジ値を出力
        range = quantize(Capacity);
        // レンジ値を SVG の data-classification 属性に入力
        evt.node.setAttribute("data-classification", range);
    });
    

     

    ArcGIS API for JavaScript のみ

    // 数値分類用オブジェクトの配列
    var classbreaks = [
        {
            attribute: "0",
            value: 308
        },
        {
            attribute: "1",
            value: 606
        },
        {
            attribute: "2",
            value: 904
        },
        {
            attribute: "3",
            value: 1202
        },
        {
            attribute: "4",
            value: 1500
        }
    ];
    
    // 避難所グラフィック描画時に実行
    on(hinanjo, "graphic-draw", function (evt) {
        var tableAttr = evt.graphic.attributes["収容人数"];
        var category;
        if (tableAttr < classbreaks[0].value) {
            category = classbreaks[0].attribute;
        } else if (tableAttr >= classbreaks[0].value && tableAttr < classbreaks[1].value) {
            category = classbreaks[1].attribute;
        } else if (tableAttr >= classbreaks[1].value && tableAttr < classbreaks[2].value) {
            category = classbreaks[2].attribute;
        } else if (tableAttr >= classbreaks[2].value && tableAttr < classbreaks[3].value) {
            category = classbreaks[3].attribute;
        } else if (tableAttr >= classbreaks[3].value && tableAttr < classbreaks[4].value) {
            category = classbreaks[4].attribute;
        }
        // カテゴリの値を SVG の data-classification 属性に入力
        evt.node.setAttribute("data-classification", category);
    });
    

     

     

    おまけ:cedar.js

    cedar.js とは Esri がメンテナンスしているオープンソースの JavaScript ライブラリであり、ArcGIS の Web サービスをソースとしたデータ ビジュアライゼーションの実現を容易にしてくれます。この cedar.js は D3.js を利用して作られているので、ArcGIS API for JavaScript と D3 の連携によるデータ ビジュアライゼーションを実現したい場合は cedar.js を採用するのが最善の選択肢かもしれません。

     

    本稿では詳しい実装方法は紹介しませんが、cedar.js のページにてサンプル コードや API リファレンスが掲載されていますので、興味のある方は参照してみてください。

     

    cedar.js | Esri Cedar

    cedar.png

     

    以上、ArcGIS API for JavaScript の D3 連携による表現方法をご紹介してきました。紹介した方法は非常に簡単な連携例となっていますが、D3 を使うことでデータ ビジュアライゼーションを実現するためのロジックが簡易化されるだけでなく、cedar.js のように高度なデータ表現をアプリ上に作り出すことも可能です。

     

    ひきつづき JavaScript で始めるデータ ビジュアライゼーションについてご紹介していく予定ですので、今後もぜひご期待ください。