Rechartsの棒グラフで年ごとにバーの色を自動で変える方法
はじめに
先日、Rechartsで棒グラフを作成していた際に「年ごとにバーの色を変える」という仕様を実装しました(最終的には採用しませんでしたが)。
当初はX年後くらいまで各年に対応する色をハードコーディングしようかと思いました。
しかし、それではあまりにもスマートではありません。
そこで、以下の要件を満たすロジックを組むことにしました。
- 色が自動で割り当てられる
- 隣り合う年同士の色のバランスが良い感じになる
- 再読み込みをしても、同じ年には同じ色が割り当てられる
今回はその実装方法を紹介します。
完成イメージ
年が変わるたびにバーの色が切り替わり、隣り合う年の色が似ない配色になります。
再読み込みをしても年ごとの色は固定されています。(「2020年のバーの色が青だったのに、再読み込みしたら赤になった」みたいなことは起きない)

実装
年ごとの色を生成する関数
const getColorForYear = (year: number): string => {
const hue = (year * 137.508) % 360
return `hsl(${hue}, 70%, 55%)`
}
137.508°は黄金角と呼ばれるもので、360° × (1 - 1/φ) ≈ 137.508°(φは黄金比)です。
この関数では、黄金角を用いて色相環を循環する形で色を指定しています。
この角度ずつ色相環を回転させると、連続する値(隣り合う年)でも色相環上でなるべく離れた位置の色が配置されます。
均等分割(360 / 年数)でも色分けはできますが、黄金角を使うと年数が事前にわからなくても常にバランスよく色が散るのがメリットです。
使用イメージ&ポイント解説
Cellコンポーネントで個別に色を指定
Rechartsの<Bar>に単一のfillを指定すると全バーが同じ色になります。
バーごとに異なる色を指定するには、<Bar>の子要素として<Cell>をdata.map()でレンダリングします。
各Cellは対応するバーのfillに色を適用します。
<Bar dataKey="count">
{data.map((item) => {
const year = Number(item.yearMonth.split('-')[0])
return <Cell key={item.yearMonth} fill={getColorForYear(year)} />
})}
</Bar>
まとめ
- Rechartsでバーごとに色を変えるには
<Cell>コンポーネントを使う - 黄金角(137.508°)で色相を回転させると、年数が不定でもバランスの良い配色になる
以上、共有でした。







