Javascript (D3+React_ツリーサンプル)
■簡単なサンプル02。
D3+Reactで何ができるか試行錯誤中。今回はツリーのサンプル。
このブログのカテゴリーに対して投稿数をサイズとしてツリー状にしてみた。

サンプルコードはChat GPTで生成した(参考に一番下につける)。
useStateの中でデータを持ち、D3として d3.hierarchy、d3.tree()、d3.scaleLinear を使っている。
このコードの実行結果が下。

上の図もこちらの図も1つの値を葉ノードのサイズに使っているだけで、親から子ノードへの距離や子ノード間の距離は特に指定していない。相関性に関わる指標をデータとして入れればもう少し意味のある図になるだろうけど、いい感じのものが思いつかない。ブログであれば、各記事の本文中でどれだけ同じワードが出てくるかとかで相関性とかを数値化できるかもしれない。
サンプルコード
import { useState } from "react";
import * as d3 from "d3";
export default function RadialTree() {
const [data, setData] = useState({
name: "Root",
value: 20,
children: [
{
name: "Branch A",
value: 5,
children: [
{ name: "Leaf A1", value: 3 },
{ name: "Leaf A2", value: 2 }
]
},
{
name: "Branch B",
value: 4,
children: [
{ name: "Leaf B1", value: 3 }
]
},
{
name: "Branch C",
value: 13,
children: [
{ name: "Leaf C1", value: 10 },
{ name: "Leaf C2", value: 6 },
{ name: "Leaf C3", value: 2 },
{ name: "Leaf C4", value: 5 }
]
}
]
});
const width = 500;
const height = 500;
const radius = 200; // ツリーのサイズ
// ▼ D3: 階層構造と radial レイアウト計算
const root = d3.hierarchy(data);
const treeLayout = d3.tree().size([2 * Math.PI, radius]);
treeLayout(root);
// ▼ ノードサイズ(value で円の大きさを調整)
const sizeScale = d3.scaleLinear().domain([0, 10]).range([5, 20]);
// ▼ 極座標 → XY 変換
const project = (angle, r) => {
return [
r * Math.cos(angle - Math.PI / 2),
r * Math.sin(angle - Math.PI / 2)
];
};
return (
<svg
width={width}
height={height}
style={{ border: "1px solid #ccc" }}
>
<g transform={`translate(${width / 2}, ${height / 2})`}>
{/* ▼ 枝(links) */}
{root.links().map((link, i) => {
const [sx, sy] = project(link.source.x, link.source.y);
const [tx, ty] = project(link.target.x, link.target.y);
return (
<line
key={i}
x1={sx}
y1={sy}
x2={tx}
y2={ty}
stroke="#777"
/>
);
})}
{/* ▼ ノード */}
{root.descendants().map((node, i) => {
const [x, y] = project(node.x, node.y);
return (
<g key={i} transform={`translate(${x},${y})`}>
<circle
r={sizeScale(node.data.value)}
fill="#69b3a2"
stroke="#333"
/>
<text
dy="0.35em"
x={node.x < Math.PI ? 10 : -10}
textAnchor={node.x < Math.PI ? "start" : "end"}
fontSize={12}
>
{node.data.name} ({node.data.value})
</text>
</g>
);
})}
</g>
</svg>
);
}

