Chart.jsでベースカラーから動的に色を生成しながら円グラフを描画する
Chart.jsで円グラフを表示する
1年以上前
API側でデータを準備してあげて、Doughnutのdataに登録する。
tsx
'use client';
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import {
Chart as ChartJS,
ArcElement,
Tooltip,
Legend,
type ChartData,
} from 'chart.js';
ChartJS.register(ArcElement, Tooltip, Legend);
const options = {
plugins: {
legend: {
labels: {
padding: 8,
},
},
},
};
export const Container = (): JSX.Element => {
const { data } = useGetMeDashboard();
if (!data) {
return <LinearLoading />;
}
const labels = data.categoryItemCounts
? data.categoryItemCounts.map((item) => item.categoryName)
: ['データなし'];
const datasetsData = data.categoryItemCounts
? data.categoryItemCounts.map((item) => item.itemCount)
: [1];
const categoryItemCountsLength = data.categoryItemCounts?.length ?? 1;
const baseColor = data.categoryItemCounts ? '#F9BD46' : '#FDE08F';
// pieChartData作成
const pieChartData: ChartData<'doughnut'> = {
labels,
datasets: [
{
data: datasetsData,
backgroundColor: generateBackgroundColors(
baseColor,
categoryItemCountsLength
),
borderWidth: 1,
spacing: 2,
},
],
};
<Doughnut
data={pieChartData}
options={{
...options,
maintainAspectRatio: true, // アスペクト比を維持
responsive: true, // レスポンシブ対応
}}
/>;
};Chart.jsで利用する円グラフの色を自動生成する
1年以上前
baseColorを元に、同系色で徐々に色を変化する様にしている。
ts
export const generateBackgroundColors = (
baseColor: string,
count: number
): string[] => {
const colors: string[] = [];
for (let i = 0; i < count; i++) {
const hsl = hexToHsl(baseColor);
const saturation = hsl.s + i * (50 / count); // 彩度を徐々に増やす
const lightness = hsl.l + i * (35 / count); // 輝度を徐々に上げる
const color = `hsl(${hsl.h}, ${saturation}%, ${lightness}%)`;
colors.push(color);
}
return colors;
};
// 16進数のカラーコードをHSL表現に変換する関数
const hexToHsl = (hex: string): { h: number; s: number; l: number } => {
const r = parseInt(hex.substring(1, 3), 16) / 255;
const g = parseInt(hex.substring(3, 5), 16) / 255;
const b = parseInt(hex.substring(5, 7), 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h = 0;
let s = 0;
const l = (max + min) / 2;
if (max === min) {
h = s = 0; // achromatic
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100),
};
};