rechartsの円グラフ入門(TypeScript)
記事作成時の recharts のバージョン: 2.12.7
はじめに
React でグラフを描画するライブラリの1つにrechartsがあります。
今回、業務で recharts を使って円グラフを作成する機会があったので、公式サイトのサンプルコードの読み解きと自分なりのカスタマイズを行いました。
下記で記載するコードはすべて github 上にアップしています。
(recharts や React, TypeScript のバージョンなども github のコードを見てください)
TwoLevelPieChart
公式のサンプルコード:https://recharts.org/en-US/examples/TwoLevelPieChart
ドーナッツ状の円グラフの中に、普通の形の円グラフが入っている形状をしています。
一見2つの円グラフは何かしらの関係を持っていそうですが、実際は完全に独立しています。
import { PieChart, Pie, ResponsiveContainer, Tooltip } from "recharts";
const data01 = [
{ name: "Group A", value: 400 },
{ name: "Group B", value: 300 },
{ name: "Group C", value: 300 },
{ name: "Group D", value: 200 },
];
const data02 = [
{ name: "A1", value: 100 },
{ name: "A2", value: 300 },
{ name: "B1", value: 100 },
{ name: "B2", value: 80 },
{ name: "B3", value: 40 },
{ name: "B4", value: 30 },
{ name: "B5", value: 50 },
{ name: "C1", value: 100 },
{ name: "C2", value: 200 },
{ name: "D1", value: 150 },
{ name: "D2", value: 50 },
];
export const TwoLevelPieChart = () => {
return (
<ResponsiveContainer width="80%" height={400}>
<PieChart>
<Pie data={data01} dataKey="value" outerRadius="60%" fill="#8884d8" />
<Pie
data={data02}
dataKey="value"
innerRadius="70%"
outerRadius="80%"
fill="#82ca9d"
paddingAngle={5}
label={{ fontSize: "1.5em" }}
/>
<Tooltip />
</PieChart>
</ResponsiveContainer>
);
};
<PieChart><Pie /></PieChart>
のように、
PieChart
コンポーネントを親、Pie
コンポーネントを子として使います。
上記のように2種類の円グラフを書きたい場合は、Pie
コンポーネントを2つ使います。
Pie
コンポーネントの超基本的なプロパティは以下です。
-
data
- 円グラフに使用するデータのオブジェクトを指定します
-
dataKey
-
data
で指定したオブジェクトの中で、円グラフの値として使うプロパティを指定します
-
-
fill
- 円グラフの色を指定します
-
label
-
label={true}
とすると円グラフにラベルが表示されます。デフォルトはfalse
です。
-
公式のサンプルコードからカスタマイズした点
-
Pie
コンポーネントのプロパティ-
cx
,cy
- 円グラフの中心座標を指定します
- 公式のサンプルコードでは
200
などの値で指定されていますが、デフォルトはcx
,cy
とも50%
であり、大体のケースではデフォルトのままで問題ないかと思います。 - そのため上記のサンプルコードではプロパティの指定を省略しています。
-
outerRadius
- 円グラフの大きさ(厳密には外側の円の大きさ)を指定します
- デフォルトは
80%
であり、こちらも基本的にはデフォルトのままで良いかと思います。 - 上記のような2つの円グラフを重ねるケースでは、このプロパティの値を指定して調整する必要があります
- 公式のサンプルコードでは
70
などの値で指定されていますが、%による指定の方がレスポンシブ対応しやすいかと思うので%での指定に変更しました。
- 公式のサンプルコードでは
-
innerRadius
- デフォルトは
0%
であり、これを 0 より大きくするとドーナツ型の円グラフになります。
(値が大きいほど穴が大きいドーナツになります) - 公式のサンプルコードでは
70
などの値で指定されていますが、%による指定の方がレスポンシブ対応しやすいかと思うので%での指定に変更しました。
- デフォルトは
-
paddingAngle
- 円グラフの要素間のスペースの大きさを指定します。デフォルトは
0
です。 - 見栄えを良くするためのプロパティのため、特に指定せずとも問題ないです。
- また説明が難しいですが、ドーナツ型ではない円グラフにこのプロパティを指定すると歪な感じになるため、基本ドーナツ型の円グラフでのみ使用することになりそうです。
- 円グラフの要素間のスペースの大きさを指定します。デフォルトは
-
label
- デフォルトの設定(
true
)では円グラフの大きさとラベルの文字フォントの大きさが連動しません。 - そのため、
{ fontSize: "1.5em" }
のようにフォントサイズをオブジェクトで渡すことでフォントサイズを可変にしています。
- デフォルトの設定(
-
- 追加したコンポーネント
-
ResponsiveContainer
- recharts で作成したグラフをレスポンシブ対応させるには、
ResponsiveContainer
コンポーネントで囲む必要があるので追加しました。 - 横幅でレスポンシブ対応させる場合は、このコンポーネントに
width="80%"
などのように相対的に指定しておけば OK です。 - 公式:https://recharts.org/en-US/api/ResponsiveContainer
- recharts で作成したグラフをレスポンシブ対応させるには、
-
Tooltip
- このコンポーネントを追加することで、ホバーした際にデータの情報(ツールチップ)の表示をさせることができます。
- 要するにグラフの UI がより良い感じになります。
- ツールチップがあることで困るケースはほぼ無いかと思うので、基本的には追加しておくで良いかと思います。
-
StraightAnglePieChart
半円の形をした円グラフです。
公式のサンプルコード:https://recharts.org/en-US/examples/StraightAnglePieChart
import { PieChart, Pie, ResponsiveContainer, Tooltip } from "recharts";
const data = [
{ name: "Group A", value: 400 },
{ name: "Group B", value: 300 },
{ name: "Group C", value: 300 },
{ name: "Group D", value: 200 },
{ name: "Group E", value: 278 },
{ name: "Group F", value: 189 },
];
export const StraightAnglePieChart = () => {
return (
<ResponsiveContainer width="80%" height={400}>
<PieChart>
<Pie
dataKey="value"
startAngle={180}
endAngle={0}
data={data}
fill="#8884d8"
label={{ fontSize: "1.5em" }}
/>
<Tooltip />
</PieChart>
</ResponsiveContainer>
);
};
-
Pie
コンポーネントのプロパティ-
startAngle
- 円グラフの開始位置を指定します
-
0
で 3 時の位置、90
で 12 時の位置、-90
で 6 時の位置、、、のように調整できます - デフォルトの値は
0
です
-
endAngle
- 円グラフの終了位置を指定します
- 数値による指定方法は
startAngle
と同じです - デフォルトの値は
360
です
-
TwoSimplePieChart
1つの描画領域に2つの円グラフを並べて表示しています。
公式のサンプルコード: https://recharts.org/en-US/examples/TwoSimplePieChart
import { PieChart, Pie, Tooltip, ResponsiveContainer } from "recharts";
const data01 = [
{ name: "Group A", value: 400 },
{ name: "Group B", value: 300 },
{ name: "Group C", value: 300 },
{ name: "Group D", value: 200 },
{ name: "Group E", value: 278 },
{ name: "Group F", value: 189 },
];
const data02 = [
{ name: "Group A", value: 2400 },
{ name: "Group B", value: 4567 },
{ name: "Group C", value: 1398 },
{ name: "Group D", value: 9800 },
{ name: "Group E", value: 3908 },
{ name: "Group F", value: 4800 },
];
export const TwoSimplePieChart = () => {
return (
<ResponsiveContainer width="80%" height={400}>
<PieChart>
<Pie
dataKey="value"
isAnimationActive={false}
data={data01}
cx="25%"
fill="#8884d8"
label={{ fontSize: "1.5em" }}
/>
<Pie
dataKey="value"
data={data02}
cx="75%"
innerRadius="40%"
outerRadius="80%"
fill="#82ca9d"
/>
<Tooltip />
</PieChart>
</ResponsiveContainer>
);
};
-
Pie
コンポーネントのプロパティ-
isAnimationActive
- 円グラフの表示の際にアニメーションを行うかを設定できます
- デフォルトは
true
(アニメーションあり)です
-
PieChartWithCustomizedLabel
円グラフの各要素に異なる色になっており、かつラベルが円グラフの中に表示されています。
(巷でよく見る円グラフはこのデザインが多い気がします)
公式のサンプルコード:https://recharts.org/en-US/examples/PieChartWithCustomizedLabel
import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer } from "recharts";
const data = [
{ name: "Group A", value: 400 },
{ name: "Group B", value: 300 },
{ name: "Group C", value: 300 },
{ name: "Group D", value: 200 },
];
const COLORS = ["#0088FE", "#00C49F", "#FFBB28", "#FF8042"];
const RADIAN = Math.PI / 180;
type Props = {
cx: number;
cy: number;
midAngle: number;
innerRadius: number;
outerRadius: number;
percent: number;
};
const renderCustomizedLabel = ({
cx,
cy,
midAngle,
innerRadius,
outerRadius,
percent,
}: Props) => {
// ちょうどいい位置にラベルを表示するための計算
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
const x = cx + radius * Math.cos(-midAngle * RADIAN);
const y = cy + radius * Math.sin(-midAngle * RADIAN);
return (
<text
x={x}
y={y}
fill="white"
textAnchor={x > cx ? "start" : "end"}
dominantBaseline="central"
fontSize="1.5em"
>
{`${(percent * 100).toFixed(0)}%`}
</text>
);
};
export const PieChartWithCustomizedLabel = () => {
return (
<ResponsiveContainer width="80%" height={400}>
<PieChart>
<Pie
data={data}
dataKey="value"
labelLine={false}
label={renderCustomizedLabel}
fill="#8884d8"
>
{data.map((_entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip />
</PieChart>
</ResponsiveContainer>
);
};
円グラフの内側にラベルを表示する
Pie
コンポーネントのlabel
プロパティに DOM 要素を返す関数を設定することで、円グラフのラベルを自由にカスタマイズすることができます。
上記のサンプルコードでこれを行っているのがrenderCustomizedLabel
関数で、円グラフの各要素(扇形の部分)の真ん中にラベルを表示するような SVG のtext
要素を返しています。
真ん中の位置を求める計算はなにか組み込みの便利な関数があるのか、、、と思いきや三角関数を使って自前でゴリゴリ計算しています。
円グラフの要素ごとの色の設定
これまでの例のようにPie
コンポーネントに通常の props を渡すのではなく、<Pie><Cell /></Pie>
の形でCell
コンポーネントを children として渡しています。
このCell
コンポーネントのfill
プロパティに任意の色を設定することで、円グラフの要素ごとの色を設定できるようになります。
CustomActiveShapePieChart
文量が多くなったので別記事にしました。
まとめ
recharts の円グラフの基本的な使い方を紹介しました。
正直、データ分析の領域では Tableau や Power BI などが普及していく中で、円グラフを JavaScript で書きたいニーズはとても限定的な気がしますが、
スクラッチのアプリケーションに組み込みたい場合では便利なライブラリだと感じました。
(あとやっぱり自分で作るのは楽しい)
Discussion
shadcnにrechatのcomponent増えたので、そちらも参照してリライトしてもいいかもですね