スコット・マレイ
コード・アーティスト

Tutorials > D3 > SVG の描画

SVG の描画

最終更新日 2012年12月30日(原文)  2013年04月05日(翻訳 / h.sakai

前章で SVG 画像とその要素の基本的仕組みについてはしっかり理解できたでしょうか?本章ではいよいよデータからシェイプを生成する方法に入ります。

すでにお気づきの方もおいででしょうが、SVG 要素のプロパティはすべてその要素の属性として指定します。各要素のタグ内に、プロパティと値の組み合わせとして記述するのです。下がその一般式です。

<element property="value"/>

そうです、これは通常の HTML 要素とまったく同じ書式です。

<p class="eureka">

HTML 要素の新規生成とその属性の設定は、便利な D3 の append()attr() メソッドを使って行います。SVG 要素も、DOM の部品である点に関しては HTML 要素と変わりありません。つまり SVG 画像も、HTML 要素と同様に append()attr() を使って生成できるのです。

SVG の生成

まず最初に SVG 要素の生成です。すべてのシェイプはこの SVG 要素の中に配置されます。

d3.select("body").append("svg");

この式は body を検索し、その終了タグ </body> の直前に svg 要素を新規追加します。これでも問題はありませんがもう一工夫してみましょう。

var svg = d3.select("body").append("svg");

ここでほとんどの D3 メソッドは操作した要素の参照を返す、ということを思い出してください。この式は append() が生成した要素の参照を、新しい変数 svg に記録しています。この変数 svg は、単なる変数ではなく、新規に生成した SVG オブジェクトを指す参照であると理解してください。参照を変数に記録しておけば、あとあと無駄なコードを書く手間がはぶけます。また毎回 d3.select("svg") を使って DOM 内を検索するより svg を呼ぶ方が高速になります。

svg.attr("width", 500)
   .attr("height", 50);

上記のコードを一行にまとめて書くこともできます。

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

サンプルページをご覧ください。空白のページが表示されますが、例により WEB インスペクタを立ち上げると、ちゃんと空の SVG 要素が生成されているのがわかります。

面倒を避けるため、幅( width )と高さ( height )の二つの値は、このページのように(ソースコード参照)、コードの最初で変数定義しておくことをお勧めします。

// width と height
   var w = 500;
   var h = 50;

今後のサンプルもこの方針に沿って書いて行きます。二つの値を変数化しておく(※ variabalize )ことで、コード全体から容易に参照可能になるからです。

var svg = d3.select("body")
            .append("svg")
            .attr("width", w)   // <-- ここ!
            .attr("height", h); // <-- ここにも!

※ variabalize という単語は存在しませんが、もしこの単語を辞書に登録しようという運動があったら喜んで署名させていただきます(笑)

データドリブン・シェイプ

いよいよシェイプの追加です。お馴染みのデータセットに再登板してもらいましょう。

var dataset = [ 5, 10, 15, 20, 25 ];

作るのは円シェイプです。data() メソッドを使い、各データポイントごとに circle を生成します。

svg.selectAll("circle")
   .data(dataset)
   .enter()
   .append("circle");

selectAll() メソッドがすべての circle要素の空参照(この時点ではまだ circle 要素は存在していません!)を返すのを憶えていますか?data() メソッドは、データセットとこれから生成する要素をバインドします。次に enter() メソッドが新しく作る要素のためのプレイスホルダーの参照を提供し、最後にappend() メソッドが circle 要素を DOM に追加して行きます。

ここでも後々のため、生成する circle 要素への参照を変数に記憶しておきます。

var circles = svg.selectAll("circle")
                 .data(dataset)
                 .enter()
                 .append("circle");

OK です。次にこの円に位置とサイズを設定します。いきなり複雑なコードが登場しますが、ここでくじけないように!

circles.attr("cx", function(d, i) {
             return (i * 50) + 25;
         })
        .attr("cy", h/2)
        .attr("r", function(d) {
             return d;
        });

Row of data circles

実際に表示されるのはそんなに複雑な画面ではありませんね?。コードを一行ずつ順番に理解して行きましょう。

circles.attr("cx", function(d, i) {
            return (i * 50) + 25;
        })

一行目はすべての circle 要素の参照を受け取り、それぞれに cx 属性を設定しています。cx の値の設定には無名関数を使っています。データはすでに circle 要素とバインドされているため、仮引数 d には、元のデータセット (5, 10, 15, 20, 25) の対応する値が渡されます。

引数 i には現在の値のインデックス番号が渡されます。attr() の値を設定する無名関数に第二引数を指定すると、data() メソッドの働きにより、現在の値が配列内の何番目の要素であるかを示す数字(インデックス番号)が i に自動的にセットされるのです。i は 0 から始まる整数値で、1番目の要素は i == 0、2番目は i == 1、以下同様となります。この行では、ループごとに i が 1 ずつ増加するのを利用して、円の位置を順次右へと配置しています。

(0 * 50) + 25 = 25
(1 * 50) + 25 = 75
(2 * 50) + 25 = 125
(3 * 50) + 25 = 175
(4 * 50) + 25 = 225

インデックス値の i を使うにはこれを無名関数の引数に含めておく必要があります(function(d, i))。また、今回の例のように関数内で使わない場合でも、引数には d は含めておかなければなりません。もしここで function( i ) としても、i には元の式の d の値が渡されるだけです。なお、iも仮引数ですので、ここに jkindex を使っても問題はありません。慣例的には i を使います。

次に 2 行目です。

.attr("cy", h/2)

h は SVG 要素全体の高さでした。したがって h/2 はその半分の高さとなります。h を変数で定義しておいたのが役立ちましたね。この式によって、すべての circle 要素の中心位置は、同じ高さで横一線に並ぶことになります。

.attr("r", function(d) {
   return d;
});

最後の行で各 circle の半径 r を設定します。ここでは、そのまま d の値、すなわち対応するデータの値を設定しています。

シェイプの彩色

塗り( fill )と線( stroke )の色も、同じ attr() メソッドの別の属性で指定できます。次のコードを追加するだけです。

.attr("fill", "yellow")
.attr("stroke", "orange")
.attr("stroke-width", function(d) {
    return d/2;
});

できあがりです!(サンプル画面はこちら

Colorful data circles

この章で解説したサンプルは、もちろん SVG の使い方のほんの一例に過ぎません。自分で属性の組み合わせや関数の中身を工夫したり、プロパティの値を色々変更してみましょう。読み手に分かりやすく有益となるような上手なデータ視覚化を行う秘訣は、最適なマッピング(データを要素に対応付けること)を選択することにあります。

次章はデータ型

インタラクティブ・データ・ヴィジュアライゼーション このチュートリアルの書籍版の翻訳がオライリー・ジャパンより発売されました。タイトルは『インタラクティブ・データビジュアライゼーション ―D3.jsによるデータの可視化』です(画像をクリックするとアマゾンに飛びます)。

このチュートリアルを大幅に拡充し、3倍近い内容となっています。JavaScriptを中心に基礎編をさらに詳しく解説し(書籍版第3章)、応用編としてモーション、イベント、レイアウト、地図の作成法、データのエクスポート(PDFやSVG等)の章が追加されています(同9章~13章)。アマゾンのページで目次を見ることができます。

本チュートリアルがわかりにくいと感じられた方、あるいは本チュートリアルを終え、さらに応用力を身につけたいと思われた方のどちらにもお勧めの内容となっています。

翻訳はコンピュータ・プログラミング関連書籍を多数翻訳されている長尾高弘氏です。