D3を使ってグラフを書く準備をする
D3の実行方法とSVGの関係が分かったところで、ここからはD3が持つ数値データをグラフ化していくための、基本的な部分を説明していきます。
D3でグラフの軸を表示する
図11の通り、数学などでよく使うXY軸をD3の機能を使って描写します。

これを実現するためのコードがリスト3です。
const ele = document.getElementById("canvas"); // (1) X軸と画面上の位置の関係 const x = d3.scaleLinear() .domain([0, 300]) .range([40, 900 - 20]); // 余白を考慮 // (2) Y軸と画面上のY位置の関係 const y = d3.scaleLinear() .domain([0, 100]) .range([600 - 30, 20]); // 余白を考慮 const contents = d3.select(ele); const svg = contents.append("svg") .attr("width", 900) .attr("height", 600); // (3) X軸を配置する svg.append("g") .attr("transform", `translate(0,${600 - 30})`) // 余白を考慮 .call(d3.axisBottom(x)); // (4) Y軸を配置する svg.append("g") .attr("transform", `translate(${40},0)`) // 文字列内変数の利用である{}を使った表記はあえて(3)とあわせている .call(d3.axisLeft(y));
この処理では非常に基本的な考え方が含まれるので図12で説明します。

(1)ではX軸のデータ上の範囲と画面上の範囲を考慮したスケールを作成しています。同様に(2)ではY軸のデータ上の範囲と画面上の範囲を考慮したスケールを作成しています。スケールとは、データ上の値から画面上の位置を示す値を求める関数です。
domainとはデータ範囲、rangeとは画面上の範囲を示します。X軸では、データの0~300を画面範囲を40~880へと変換するという意味になります。
ここで気をつけるべきは、Y軸の場合、データは0〜100に対して、画面範囲は570〜20と反対向きになることです。例えば、リスト4のようにすれば、実際の位置を計算できます。
x(58); // X軸の58の位置は 202.39999999999998 y(40); // Y軸の40の位置は 350
また、scaleLinearの「Linear」は比例という意味で、数学では一般的な軸がこのLinear軸です。これ以外にも数学では対数軸や時間軸などを使ってきたと思います。
そして(3)(4)で実際の軸をどの場所に配置するかを決めています。また、axisBottomは、グラフ下に配置する場合の表示に適した軸を作る処理になります。
g要素とは、配下の要素のグループ化のことであり、HTMLであればdivタグのようなものと捉えてもらって問題ありません。そして、transformでその位置移動を行います。X軸は(40,0)、Y軸は(0,570)に移動しています。
また、callは指定された処理を実行し、その親要素(この場合には新たに作成したg要素)内に追加します。axisBottomは指定されたスケールを用いて、ラベルが下部分、メモリが上に向いている軸を作る処理であり、その処理をcallを通じて実行し、そして、それらを包括した親要素であるg要素に対してtransformにて移動するという一連の流れになります。同様に、axisLeftは左側表示用の軸になります。
軸の位置を変える
続いて、先ほどの例の応用として図13のように、軸の移動と値の位置をわかりやすくするグリッドを描写する例を考えます。

表示する画面サイズは変更しない前提で、実際のデータ範囲を変える場合にはリスト4のように軸のデータ範囲が変わります。
const ele = document.getElementById("canvas"); // (1) X軸と画面上の位置の関係 const x = d3.scaleLinear() .domain([-150, 150]) .range([40, 900 - 20]); // (2) Y軸と画面上のY位置の関係 const y = d3.scaleLinear() .domain([-100, 100]) .range([600 - 30, 20]); // (省略) // (3) (0,0)の位置を求める const x_zero = x(0); const y_zero = y(0); // (4) X軸を配置する svg.append("g") .attr("transform", `translate(0,${y_zero})`) .call(d3.axisBottom(x)); // (5) Y軸を配置する svg.append("g") .attr("transform", `translate(${x_zero},0)`) .call(d3.axisLeft(y)); // (6) グリッド表示する為のg(グループ)要素を作成する const grid = svg.append("g") .attr('class','-grid'); // (7) X軸用のグリッドを表示する for(let yy = -100; yy <= 100; yy += 20){ grid.append("line") .attr("x1", x(-150)).attr("y1", y(yy)).attr("x2", x(150)).attr("y2", y(yy)); } // (8) Y軸用のグリッドを表示する for(let xx = -140; xx <= 140; xx += 20){ grid.append("line") .attr("x1", x(xx)).attr("y1", y(-100)).attr("x2", x(xx)).attr("y2", y(100)); } // (9) 背景を表示する grid.append("rect").attr('class','-grid-bg') .attr("x",x(-150)).attr("y",y(100)) .attr("width",x(150) - x(-150)).attr("height",y(-100) - y(100));
(1)(2)で変わった部分はdomain範囲のみです。(3)では、作成したスケールを使って、座標(0,0)の位置を求めておきます。そして、(4)ではX軸をy(0)の位置に、(5)ではY軸をx(0)の位置に配置します。(6)ではグリッド用のグループ(g)を作成しています。
これ以降は、D3の便利機能は使わず、SVGの要素を記述しています。(7)(8)でのグリッド用の縦線と横線を記述するには、SVGでのline要素を使います。このline要素は始点(x1,y1)と終点(x2,y2)を指定して線を描写します。
そして(9)でデータ領域をすべてカバーする四角形(rect)を用いて描写しています。SVG要素内でも色なども指定できますが、CSSで変更する事が可能ですので、ここではclass属性を使っています。
最後に
筆者は中学生ぐらいからBASICという言語でプログラミングを始めました。当時は、数学とプログラムの関係について何も感じていませんでした。しかし、高校数学において関数の和を示すΣ(シグマ記号)を学んだ時に、これはプログラムでいうFOR文と同じだと感じました。そのときから、Σを見ると何か分からないルールが「繰り返し」処理されるといったイメージを持つようになりました。
「詳細はよく理解できないけれど、なんとなくイメージとして分かった気になれる」ことは、プログラムにおいて非常に大切だと思います。特に現在の開発では最初から最後まですべて理解することは不可能になりつつあります。理解できない複雑な部分を自分が知っている簡単なルールに置き換えてイメージすることができれば、データ分析やAIといった難しい処理の応用もわかりやすくなるのではないかと思います。