前回まででメインのグラフは描画できました。今回は X 軸などグラフに必要な他の要素を描写します。
X 軸
d3 の機能を使って X 軸が簡単に描写できます。
1. まず X 軸の描写領域用の入れ物を定義。Visual クラスのプロパティに以下コードを追加。
private xAxis: d3.Selection<d3.BaseType, any, any, any>;
2. コンストラクタ内で初期化。ルートの SVC に対して g 要素を追加。
constructor(options: VisualConstructorOptions) {
this.svg = d3.select<SVGElement, any>(<any> options.element)
.append('svg');
this.stackBarContainer = this.svg
.append('g');
this.xAxis = this.svg
.append('g');
}
3. X 軸を表示できるようグラフ領域のマージンを変更。
let margin = { top: 0, bottom: 30, left: 0, right: 0 }
4. update 関数の一番下に以下コードを追加。
- transform 要素を使って表示場所を下に移動
- d3.axisBottom に、定義した x 関数を渡して X 軸を作成
let xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
.call(g => g.selectAll(".domain").remove());
this.xAxis.call(xAxis);
Y 軸
ほぼ X 軸と同じように実装できます。
1. Y 軸の描写領域用の入れ物を定義。Visual クラスのプロパティに以下コードを追加。
private yAxis: d3.Selection<d3.BaseType, any, any, any>;
2. コンストラクタ内で初期化。ルートの SVC に対して g 要素を追加。
this.yAxis = this.svg
.append('g');
3. Y 軸を表示できるようグラフ領域のマージンを変更。
let margin = { top: 0, bottom: 30, left: 40, right: 0 }
4. update 関数の一番下に以下コードを追加。
- transform 要素を使って表示場所を左に移動
- d3.axisLeft に、定義した y 関数を渡して Y 軸を作成
let yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(null, "s"))
.call(g => g.selectAll(".domain").remove());
this.yAxis.call(yAxis);
凡例
基本的な考え方は同じですが、凡例は通常、四角や丸などと文字列を一緒に表示するため、要素が増えます。
1. 凡例描写領域用の入れ物を定義。Visual クラスのプロパティに以下コードを追加。
private legend: d3.Selection<d3.BaseType, any, any, any>;
2. コンストラクタ内で初期化。ルートの SVC に対して g 要素を追加。
this.legend = this.svg
.append("g");
3. 凡例を表示できるようグラフ領域のマージンを変更。
let margin = { top: 0, bottom: 30, left: 40, right: 130 }
4. update 関数の一番下に以下コードを追加。
- circle と text 要素で構成するため、要素を一段階追加
- transform で画面右側に表示
- 凡例の順番とグラフの順番が逆のため、reverse() で入れ替え
- 各凡例が重ならないよう data 関数後に 20 ピクセルずつずれるよう transform を実行
let legend = svg => {
let g = svg
.attr("transform", `translate(${width - margin.right}, 0)`)
.selectAll("g")
.data(legends.reverse())
.join("g")
.attr("transform", (d, i) => `translate(0,${i * 20})`)
g.call(g => g.selectAll("circle").remove());
g.call(g => g.selectAll("text").remove());
g.append("circle")
.attr("cx", 20)
.attr("cy", 10)
.attr("r", 5)
.attr("fill", d => color(d));
g.append("text")
.attr("x", 30)
.attr("y", 9.5)
.attr("dy", "0.35em")
.text(d => d);
}
this.legend.call(legend);
まとめ
今回はメインのグラフ以外の要素を描写しました。うまく表示されているように見えますが、凡例の文字列が長くなったり、短くなったりすると動的に対応できないため、次回は提供されている Utility を使って動的に計算してみます。また書式も設定してみます。