Chord Chart
Code
ChartUtil.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"use client";
// reference: https://d3-graph-gallery.com/graph/chord_colors.html
import React, { useEffect, useCallback, useRef } from "react";
import * as d3 from "d3";
import { useResizeObserver } from "@/hooks/useResizeObserver";
import { ChartProps } from "@/types";
const ChartUtil = ({ data }: ChartProps) => {
const containerRef = useRef<HTMLDivElement | null>(null);
const matrix = data;
const renderFunc = useCallback(async () => {
const container = containerRef.current as HTMLElement;
if (!container) return;
const svg = d3
.select(container)
.html("")
.append("svg")
.attr("viewBox", "0 0 440 440")
.attr("width", "100%")
.append("g")
.attr("transform", "translate(220,220)");
const colors = ["darkcyan", "steelblue", "skyblue", "turquoise"];
const res = d3.chord().padAngle(0.05).sortSubgroups(d3.descending)(matrix);
// add the groups on the outer part of the circle
svg
.datum(res)
.append("g")
.selectAll("g")
.data(function (d) {
return d.groups;
})
.join("g")
.append("path")
.style("fill", (d, i) => colors[i])
.style("stroke", "#000")
.attr("d", d3.arc().innerRadius(205).outerRadius(210) as any);
svg
.datum(res)
.append("g")
.selectAll("path")
.data((d) => d)
.join("path")
.attr("d", d3.ribbon().radius(200) as any)
.style("fill", (d) => colors[d.source.index]) // colors depend on the source group. Change to target otherwise.
.style("stroke", "#000");
}, [matrix]);
useEffect(() => {
containerRef.current !== null && renderFunc();
}, [renderFunc]);
const resizeHandler = useCallback(() => {
containerRef.current !== null && renderFunc();
}, [renderFunc]);
useResizeObserver(containerRef, resizeHandler);
return <div ref={containerRef}></div>;
};
export default ChartUtil;