カレンダーヒートマップライブラリ比較
3つのアプローチでGitHubの草のような日別データをカレンダー形式で表示し、実装方法とスタイルを比較
📊 使用しているサンプルデータ
1年分(365日)の日別アクティビティデータを動的生成して使用しています。
// 1年分のサンプルデータを動的生成する例
const generateYearData = () => {
const data = []
const start = new Date('2024-01-01')
for (let i = 0; i < 365; i++) {
const date = new Date(start)
date.setDate(start.getDate() + i)
data.push({
day: date.toISOString().split('T')[0],
value: Math.random() < 0.3 ? 0 : Math.floor(Math.random() * 10)
})
}
return data
}出力例(一部抜粋):
[
{
"day": "2024-01-01",
"value": 0
},
{
"day": "2024-01-02",
"value": 4
},
{
"day": "2024-01-03",
"value": 7
},
{
"day": "2024-01-04",
"value": 0
},
{
"day": "2024-01-05",
"value": 2
},
{
"...": "(365件)"
}
]1. Nivo(@nivo/calendar)
@nivo/calendarパッケージでカレンダーヒートマップをネイティブサポート。fromとtoで表示期間を指定するだけで自動的に月・曜日のラベルを配置。colorScaleを使った色のカスタマイズや、ホバー時のツールチップも標準で充実している。
✓ 専用パッケージ✓ 美しいデザイン✓ D3.jsベース
import { ResponsiveCalendar } from "@nivo/calendar";
<ResponsiveCalendar
data={data} // [{ day: "2024-01-01", value: 5 }, ...]
from="2024-01-01"
to="2024-12-31"
emptyColor="#ebedf0"
colors={["#9be9a8", "#40c463", "#30a14e", "#216e39"]}
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
monthBorderColor="#ffffff"
dayBorderWidth={2}
dayBorderColor="#ffffff"
/>特徴: 専用パッケージでカレンダーヒートマップに最適化。ツールチップやアニメーションが標準搭載されており、すでにNivoを使用しているプロジェクトへの追加が容易。
tsx
'use client';
import { ResponsiveCalendar } from '@nivo/calendar';
// 日付ごとのアクティビティデータを生成
const generateData = () => {
const data = [];
const start = new Date('2024-01-01');
for (let i = 0; i < 365; i++) {
const date = new Date(start);
date.setDate(start.getDate() + i);
data.push({
day: date.toISOString().split('T')[0],
value: Math.floor(Math.random() * 10),
});
}
return data;
};
export function NivoCalendarHeatmap() {
return (
<div style={{ height: 200 }}>
<ResponsiveCalendar
data={generateData()}
from="2024-01-01"
to="2024-12-31"
emptyColor="#ebedf0"
colors={['#9be9a8', '#40c463', '#30a14e', '#216e39']}
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
monthBorderColor="#ffffff"
dayBorderWidth={2}
dayBorderColor="#ffffff"
/>
</div>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、Nivo(@nivo/calendar)を使ったカレンダーヒートマップを実装してください。
- 使用ライブラリ: @nivo/calendar の ResponsiveCalendar コンポーネント
- サンプルデータ: 1年分(365日)の日別アクティビティ数({ day: "YYYY-MM-DD", value: number }形式)を動的に生成すること
- インタラクティブ: ホバー時にツールチップで日付と値を表示すること(標準搭載)
- カラースケール: emptyColor・colors プロパティでGitHub風のグリーングラデーションを設定すること
- レスポンシブ: ResponsiveCalendar を使って親要素の幅に応じてサイズが変わるよう対応すること
- 月ラベル: from・to で表示期間を指定するだけで月・曜日ラベルが自動配置されること⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
2. カスタムReact実装(SVG)
外部ライブラリに依存せずReact + SVGでカスタム実装。日付計算とグリッド配置をJavaScriptで処理し、色のスケールも自由に定義できる。バンドルサイズへの影響がなく、デザインを完全にコントロールしたい場合に最適。
✓ 依存ゼロ✓ 完全カスタマイズ✓ 軽量
LessMore
// 色スケールの定義
const getColor = (value: number): string => {
if (value === 0) return "#ebedf0";
if (value <= 2) return "#9be9a8";
if (value <= 4) return "#40c463";
if (value <= 6) return "#30a14e";
return "#216e39";
};
// SVGでセルを描画
<svg width={width} height={height}>
{weeks.map((week, wi) =>
week.map((cell, di) => (
<rect
key={`${wi}-${di}`}
x={paddingLeft + wi * (cellSize + gap)}
y={paddingTop + di * (cellSize + gap)}
width={cellSize}
height={cellSize}
rx={2}
fill={getColor(cell.value)}
/>
))
)}
</svg>特徴: 外部依存を一切排除したピュアなReact + SVG実装。日付計算ロジックとレンダリングを自分で制御するため、完全なカスタマイズが可能。バンドルサイズへの影響がない。
tsx
'use client';
// React + SVG カスタムカレンダーヒートマップ
const getColor = (value: number): string => {
if (value === 0) return '#ebedf0';
if (value <= 2) return '#9be9a8';
if (value <= 4) return '#40c463';
if (value <= 6) return '#30a14e';
return '#216e39';
};
// 2024年1月分のサンプルデータ
const generateMonthData = (year: number, month: number) => {
const firstDay = new Date(year, month, 1).getDay();
const daysInMonth = new Date(year, month + 1, 0).getDate();
const cells = [];
for (let i = 0; i < firstDay; i++) cells.push(null);
for (let d = 1; d <= daysInMonth; d++) {
cells.push({ day: d, value: Math.floor(Math.random() * 10) });
}
return cells;
};
export function CustomCalendarHeatmap() {
const cells = generateMonthData(2024, 0); // 1月
const cellSize = 28, gap = 4;
return (
<svg viewBox={`0 0 ${7 * (cellSize + gap)} ${6 * (cellSize + gap) + 20}`}
className="w-full max-w-xs">
{['日','月','火','水','木','金','土'].map((d, i) => (
<text key={d} x={i * (cellSize + gap) + cellSize / 2} y={14}
textAnchor="middle" fontSize={9} fill="#6b7280">{d}</text>
))}
{cells.map((cell, i) => {
if (!cell) return null;
const col = i % 7, row = Math.floor(i / 7);
return (
<rect key={i}
x={col * (cellSize + gap)} y={20 + row * (cellSize + gap)}
width={cellSize} height={cellSize} rx={3}
fill={getColor(cell.value)}>
<title>{cell.day}日: {cell.value}件</title>
</rect>
);
})}
</svg>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、カスタムReact実装(SVG)を使ったカレンダーヒートマップを実装してください。 - 使用ライブラリ: 外部ライブラリなし。React + SVGのみで日付計算・グリッド配置・色スケールをすべて自前実装すること - サンプルデータ: 1年分(365日)の日別アクティビティ数を動的に生成すること - インタラクティブ: SVG の title 要素を使って各セルにホバーツールチップを実装すること - カラースケール: 値の大小に応じて5段階の色を返す getColor 関数を定義すること - レイアウト: 週を列・曜日を行とした週×7グリッドでセルを配置し、月ラベルと曜日ラベルを表示すること - 凡例: Less〜More のカラースケール凡例を下部に表示すること
⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
3. react-calendar-heatmap
react-calendar-heatmapはカレンダーヒートマップに特化した軽量ライブラリ。startDateとendDate、valuesを渡すだけでGitHub風のグラフを即座に実装できる。classForValueでCSSクラスを動的に割り当てることで色のカスタマイズも可能。
✓ 軽量✓ シンプルAPI✓ GitHub風
import CalendarHeatmap from "react-calendar-heatmap";
import "react-calendar-heatmap/dist/styles.css";
<CalendarHeatmap
startDate={new Date("2023-12-31")}
endDate={new Date("2024-12-31")}
values={[
{ date: "2024-01-01", count: 4 },
{ date: "2024-01-02", count: 7 },
// ...
]}
classForValue={(value) => {
if (!value || value.count === 0) return "color-empty";
if (value.count <= 2) return "color-scale-1";
if (value.count <= 4) return "color-scale-2";
if (value.count <= 6) return "color-scale-3";
return "color-scale-4";
}}
showWeekdayLabels
/>特徴: カレンダーヒートマップに特化したシンプルなAPI。startDate・endDate・valuesを渡すだけで動作し、CSSクラスによる色カスタマイズも直感的。
tsx
'use client';
import CalendarHeatmap from 'react-calendar-heatmap';
import 'react-calendar-heatmap/dist/styles.css';
// サンプルデータ生成
const generateValues = () => {
const values = [];
const start = new Date('2023-12-31');
for (let i = 0; i < 365; i++) {
const date = new Date(start);
date.setDate(start.getDate() + i + 1);
values.push({
date: date.toISOString().split('T')[0],
count: Math.floor(Math.random() * 10),
});
}
return values;
};
export function ReactCalendarHeatmap() {
return (
<>
<style>{`
.color-empty { fill: #ebedf0; }
.color-scale-1 { fill: #9be9a8; }
.color-scale-2 { fill: #40c463; }
.color-scale-3 { fill: #30a14e; }
.color-scale-4 { fill: #216e39; }
`}</style>
<CalendarHeatmap
startDate={new Date('2023-12-31')}
endDate={new Date('2024-12-31')}
values={generateValues()}
classForValue={(value) => {
if (!value || value.count === 0) return 'color-empty';
if (value.count <= 2) return 'color-scale-1';
if (value.count <= 4) return 'color-scale-2';
if (value.count <= 6) return 'color-scale-3';
return 'color-scale-4';
}}
showWeekdayLabels
/>
</>
);
}🤖 AIプロンプトテンプレート
React + Tailwind CSSで、react-calendar-heatmap を使ったカレンダーヒートマップを実装してください。
- 使用ライブラリ: react-calendar-heatmap パッケージの CalendarHeatmap コンポーネント、および react-calendar-heatmap/dist/styles.css
- サンプルデータ: 1年分(365日)の日別アクティビティ数({ date: "YYYY-MM-DD", count: number }形式)を動的に生成すること
- インタラクティブ: ホバーで日付と値を表示すること
- カラースケール: classForValue プロパティでCSSクラス(color-empty・color-scale-1〜4)を動的に割り当て、色をCSSで定義すること
- 設定: startDate・endDate・values・showWeekdayLabels を指定するだけで動作すること⚠️ このプロンプトはあくまでたたき台です。AIの回答はモデルやバージョン、会話の文脈によって毎回異なります。意図通りに動かない場合は、条件を追記・修正してお使いください。
ライブラリ比較
| アプローチ | レンダリング | 導入コスト | カスタマイズ性 | おすすめ用途 |
|---|---|---|---|---|
| Nivo | SVG | 低(専用パッケージ) | 高 | デザイン重視のダッシュボード |
| カスタムReact実装 | SVG | 高(自作) | 非常に高 | 独自デザインが必要な場合 |
| react-calendar-heatmap | SVG | 非常に低 | 中 | シンプルなGitHub風グラフ |
選択のポイント
- •Nivo: @nivo/calendarで最も手軽に高品質なカレンダーヒートマップを実装可能。すでにNivoを使用しているプロジェクトへの追加が容易。
- •カスタムReact実装: 外部依存を排除したい場合や、完全に独自のデザインが必要な場合に選択。実装コストはかかるが柔軟性は最高。
- •react-calendar-heatmap: 導入が最もシンプルでGitHub風のグラフをすぐに実現したい場合に最適。軽量でシンプルな用途に向いている。
典型的な使用例
- 🌱アクティビティ記録: GitHubのコントリビューショングラフのような日別活動量の可視化
- 📊売上・アクセス分析: 日別の売上やページビューの年間トレンドをひと目で把握
- 🏃習慣トラッキング: 運動・学習・瞑想などの日課の継続状況を可視化
- 📅イベント密度: カレンダー上でイベントや問い合わせの集中度を色で表現
⚠️ 使用時の注意点
- •1年分のデータ(365件)を扱うため、データ生成・取得の効率に注意する
- •色のスケール設定が重要で、値が0の日と欠損データは明確に区別する
- •週の始まりを日曜・月曜どちらにするか、ロケールに合わせて設定する
- •モバイル表示では横幅が足りなくなりやすいため、スクロール対応またはレスポンシブな縮小対応を検討する