はじめに
データ可視化、やってますか。
個人的に、Webでデータをビジュアライズしようと思ったとき、真っ先に思い浮かぶのがD3.jsなんですよね。正式名称は「Data-Driven Documents」。その名の通り、データ駆動でドキュメント(DOM)を操作するライブラリです。
GitHubスター数は驚異の11万超え。15年以上の歴史があり、今なお月間1800万〜2300万ダウンロードを誇る化け物級のライブラリです。Chart.jsやRechartsといった高レベルなチャートライブラリの多くがD3をベースにしているという話もあって、いわばデータ可視化界のレジェンド的存在ですね。
とはいえ「D3は難しい」というイメージを持っている人も多いと思います。実際、学習コストは高め。でも、その分自由度は他のライブラリとは比べ物にならないんですよ。
D3.jsの特徴・メリット
圧倒的な自由度
D3の最大の強みは、Webの標準技術(SVG、Canvas、HTML)を直接操作できること。ローレベルなAPIを提供しているので、既存のチャートライブラリではできないような独自のビジュアライゼーションも実現できます。
正直なところ、「棒グラフを表示したいだけ」ならChart.jsで十分です。でも、「このデータをこういう形で見せたい」という明確なビジョンがあるなら、D3一択ですね。
データバインディングの概念
D3の核心はデータバインディング。データとDOM要素を紐づけて、データの変化に応じてDOMを更新する仕組みです。これ、意外とReactの考え方に近いんですよ。データが変わればUIも変わる。
// データをDOM要素にバインド
d3.selectAll("rect")
.data(dataset)
.join("rect")
.attr("height", d => d.value);
豊富なモジュール群
D3は30以上のモジュールで構成されています。必要なものだけインポートすればバンドルサイズも抑えられる。フルパッケージでも96.5KB(minified + gzipped)なので、まあ許容範囲かなと。
主なモジュール:
- d3-selection: DOM操作
- d3-scale: スケール変換
- d3-axis: 軸の生成
- d3-shape: 図形の生成
- d3-transition: アニメーション
- d3-geo: 地理データの処理
アニメーションとインタラクション
トランジションAPIを使えば、スムーズなアニメーションも簡単に実装できます。グラフがぬるっと動くと、それだけでプロっぽく見えるからQOL上がりますよね。
インストール方法
npm/yarn/pnpmでインストール
プロジェクトで使うなら、パッケージマネージャー経由が基本です。
# npm
npm install d3
# yarn
yarn add d3
# pnpm
pnpm add d3
CDN経由で読み込み
プロトタイプやちょっとした検証なら、CDNが手軽です。
<!-- ESモジュール形式(推奨) -->
<script type="module">
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
</script>
<!-- UMD形式(グローバル変数として使う場合) -->
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
個人的にはESM形式を推奨します。Tree Shakingも効くし、モダンな書き方ができるので。
基本的な使い方
シンプルな棒グラフを作ってみる
まずは基本中の基本、棒グラフから。
import * as d3 from "d3";
// データ
const data = [
{ label: "A", value: 30 },
{ label: "B", value: 80 },
{ label: "C", value: 45 },
{ label: "D", value: 60 },
{ label: "E", value: 20 }
];
// サイズ設定
const width = 500;
const height = 300;
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
// SVG要素の作成
const svg = d3.select("#chart")
.append("svg")
.attr("width", width)
.attr("height", height);
// スケールの設定
const x = d3.scaleBand()
.domain(data.map(d => d.label))
.range([margin.left, width - margin.right])
.padding(0.1);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.nice()
.range([height - margin.bottom, margin.top]);
// 棒の描画
svg.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x(d.label))
.attr("y", d => y(d.value))
.attr("width", x.bandwidth())
.attr("height", d => y(0) - y(d.value))
.attr("fill", "steelblue");
// X軸
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
// Y軸
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
コード量は多めに見えますが、やっていることは単純です。スケールを定義して、データをバインドして、属性を設定する。この流れを覚えれば、大体のグラフは作れます。
Reactでの使い方
30代エンジニアならReact使っている人も多いですよね。D3とReactを組み合わせる場合は、useRefとuseEffectを使うのが定石です。
import { useRef, useEffect } from "react";
import * as d3 from "d3";
function BarChart({ data }) {
const svgRef = useRef();
useEffect(() => {
const svg = d3.select(svgRef.current);
// ここでD3の描画処理
svg.selectAll("rect")
.data(data)
.join("rect")
.attr("x", (d, i) => i * 50)
.attr("y", d => 200 - d.value)
.attr("width", 40)
.attr("height", d => d.value)
.attr("fill", "steelblue");
}, [data]);
return <svg ref={svgRef} width={500} height={300} />;
}
ポイントは、D3のDOM操作系機能(d3-selection)はuseEffect内で使うこと。スケールや図形計算系の機能はReactの外でも問題なく使えます。
実践的なユースケース
ダッシュボード構築
業務でよくあるのがダッシュボード。売上推移、ユーザー数、KPI可視化...こういうのはD3の得意分野です。リアルタイムでデータが更新されるグラフも、トランジションを使えばスムーズに表現できます。
地理データの可視化
d3-geoモジュールを使えば、地図ベースのビジュアライゼーションも可能。都道府県別のデータを色分けしたり、世界地図にプロットしたり。GeoJSONやTopoJSONとの相性も抜群です。
カスタムチャート
これ、意外と需要あるんですよ。クライアントから「こういうグラフ作れる?」と言われて、既存のライブラリでは対応できないパターン。D3ならSVGを直接操作できるので、大体なんとかなります。
インタラクティブなデータ探索
ズーム、パン、ブラッシングなど、ユーザーがデータを探索できるインタラクションも実装可能。大量のデータを扱う場合、こういった機能があるとUXが格段に上がります。
まとめ
D3.jsは、学習コストこそ高いものの、データ可視化において最強の自由度を持つライブラリです。
- 15年以上の実績、GitHubスター11万超の信頼性
- SVG/Canvas/HTMLを直接操作できる柔軟性
- 30以上のモジュールによる機能の充実
- React/Vue/Svelteなどモダンフレームワークとの併用も可能
「既存のチャートライブラリじゃ物足りない」「独自のビジュアライゼーションを作りたい」という人には、間違いなくおすすめできます。
最初はObservableでサンプルコードを動かしながら学ぶのが効率的です。公式のギャラリーを眺めるだけでも「こんなことができるのか」とインスピレーションが湧いてくると思います。
30代になって思うのは、こういう基盤技術をしっかり押さえておくと、いざというとき助かるということ。時短ツールばかり追いかけるのもいいですが、たまにはローレベルなライブラリと向き合ってみるのも悪くないですよ。