Chart.jsでベースカラーから動的に色を生成しながら円グラフを描画する

Chart.jsで円グラフを表示する

3か月前


API側でデータを準備してあげて、Doughnutのdataに登録する。

'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で利用する円グラフの色を自動生成する

3か月前


baseColorを元に、同系色で徐々に色を変化する様にしている。

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), }; };