Cal-Heatmap
githubの草(ヒートマップカレンダーと言います)のようなグラフをwebアプリで実装しようと調べまくってた時に、結構良いライブラリを発見したので、書いていきたいと思います。
jsonのようなデータを入れるだけで、カレンダーを一発で生成でき、かつ細かい設定もいじることができる優れものです。cssの羅列を書くよりはよっぽどマシだと思いました。
めっちゃがんばると、こんなのができたりします。そっくりですね
インストールとか
CDNとNPMに対応しています。
CDN
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://unpkg.com/cal-heatmap/dist/cal-heatmap.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/cal-heatmap/dist/cal-heatmap.css">
NPM
$npm install cal-heatmap
import CalHeatmap from 'cal-heatmap';
import 'cal-heatmap/cal-heatmap.css';
カレンダーのペイント
HTMLにレンダリングする場合、カレンダーの入るdiv
タグを入れておきます。
後にセレクトするため、id
やらclass
やらを指定しておくとよさそうです。
<div id="cal-heatmap"></div>
HTML側での操作はこれで以上なので、ここからはJSだけで作っていきます。
まず、CalHeatmap
クラスを呼び出し、paint
メソッドでインスタンスを構築していきます。
const cal = new CalHeatmap();
cal.paint();
Options
paint
メソッドでは、引数のOptions
オブジェクトによってカレンダーをカスタマイズする役割があります。今回は重要なところ以外は省かせていただきます。
type Options = {
itemSelector: Element | string,
range: number,
domain: DomainOptions,
subDomain: SubDomainOptions,
verticalOrientation: boolean,
date: DateOptions,
data: DataOptions,
label: LabelOptions,
animationDuration: number,
scale: ScaleOptions,
theme: 'light' | 'dark',
}
itemSelector
ここでレンダリングするタグをセレクトします。DOMかW3Cセレクターに対応しています。
cal.paint({ itemSelector: '#cal-heatmap' });
// または
cal.paint({ itemSelector: document.getElementById('cal-heatmap') });
domain
カレンダーのドメイン(画像の赤枠)の要素やフォーマットを設定できます。
cal.paint({
domain:{
type: string,
gutter: number,
padding: [number, number, number, number],
dynamicDimension: boolean,
label: LabelOptions,
sort: 'asc' | 'desc',
}
});
-
type
: ドメイン1つ分の期間(default: 'hour'
) -
gutter
: ドメイン同士の間隔px(default: 4
) -
padding
: ドメインのパディング(default: [0,0,0,0]
) -
sort
: ドメインの順序。asc
で昇順、desc
で降順(default :asc
)
subDomain
ドメイン内の子要素(画像の赤枠)の要素やフォーマットを設定できます。
cal.paint({
subdomain:{
type: string,
gutter: number,
width: number,
height: number,
radius: number,
label:
| string
| null
| ((timestamp: number, value: number, element: SVGElement) => string),
color:
| string
| ((timestamp: number, value: number, backgroundColor: string) => string),
}
});
-
type
: 子要素の期間を指定します。親のドメインで設定したtype
よりも小さい単位を設定する必要があります。(例:Domain: year => subDomain: month
) -
gutter
: 子要素同士の間隔px(default: 2
) -
width
: 子要素の横幅(default: 10
) -
height
: 子要素の縦幅(default: 10
) -
radius
: 子要素の角の丸み(default: 0
) -
color
: 子要素のlabel
の文字色(default : black
) -
sort
: 子要素の順序。asc
で昇順、desc
で降順(default : asc
)
date
カレンダーに表示する時間の範囲を設定できます。
cal.paint({
date:{
start: Date,
min: Date,
max: Date,
highlight: Date[],
locale: string | Partial<ILocale>,
timezone: string
}
});
-
start
: カレンダーの開始日(default: new Date()
) -
highlight
: 指定された子要素に目立つようなデザインが施される。 -
locale
: 週の最初の日が月曜日か日曜日か。 -
timezone
: 日付のタイムゾーン
data
カレンダーに使用するデータを設定できます。
type DataOptions = {
source: string | DataRecord[],
type: 'json' | 'csv' | 'tsv' | 'txt',
requestInit: object,
x: string | ((datum: DataRecord) => number),
y: string | ((datum: DataRecord) => number),
groupY:
| DataGroupType
| ((values: (number | string | null)[]) => number | string | null),
defaultValue: null | number | string,
};
-
source
: 使用するデータを指定します。指定の仕方は2つあります。
ローカル
プログラム内でjsonデータを作成し、引数として挿入。
const data = [
{ date: '2012-01-01', value: 3 },
{ date: '2012-01-02', value: 6 },
];
const cal = new CalHeatmap();
cal.paint({
data: {
source: data
},
});
リモート
外部ファイル、もしくは外部APIから取得したデータを入れることもできます。
const cal = new CalHeatmap();
cal.paint({
data: {
source: 'https://your-api.com/data.json'
}
});
-
type
: データのタイプを指定します。。json以外のデータタイプにも適応可能。(default: json
) -
x
: データのタイムスタンプとなるカラムのプロパティ名 -
y
: データのカウントとなるカラムのプロパティ名
xとyって?
例えば以下のようなデータを使う場合、
const data = [{ column1: '2012-01-01', column2: 3 }];
cal.paint({
data: {
source: data,
x: 'column1' ,
y: 'column2'
}
});
として挿入できる。jsonのプロパティ名は自由に設定できるのだ。
scale
ヒートマップでの色の付け方を設定できます。
cal.paint({
scale:{
opacity: {
baseColor: string,
domain: number[],
type: string
},
color: {
scheme: string,
range: string[] | d3-scale-chromatic,
interpolate: string | d3-interpolator,
domain: number[],
type: string
}
}
})
color
-
scheme
: 既存で用意されているカラーパレットが使用される。 -
range
: オリジナルのカラーパレットを指定できる。2色以上を指定する。 -
interpolate
:range
と組み合わせて使用する。色の補間範囲を定義する。 -
domain
: データセットのy
のプロパティに入る数値の最大値と最小値。type: threshold
を使用する場合は、しきい値になる。 -
type
: 配色に使用される値のタイプを指定する。-
linear(default)
- 線形変換 (平行移動とスケール) -
threshold
-domain
で設定されたしきい値によって配色される -
sqrt
- 平方根変換
などなど
-
githubの草を再現するなら、type: threshold
を使用します。
作ってみた
なんだかんだあって、データをランダムで生成させて作ってみました。
const cal = new CalHeatmap();
cal.paint(
{
itemSelector: document.getElementById('cal-heatmap'),
//or itemSelector: document.getElementById('cal-heatmap'),
domain: {
type: 'month',
gutter: 5,
label: {
text: 'MMM',
textAlign: 'start',
position: 'top'
}
},
subDomain: {
type:'ghDay',
gutter:5,
width:17,
height:17,
radius:3,
label:null
},
date: {
start: new Date('2023-01-01')
},
data: {
source: 'data.json',
x: 'date',
y: 'count'
},
scale: {
color: {
type: 'threshold',
range: ['#b0f5e5', '#35f2c6', '#0fbdb4', '#077485'],
domain: [4, 6, 8]
}
}
}
);
うまいことできてますね。
自動生成のプログラムも用意しましたのでよければ使ってみてください。
おわりに
他にもポップアウトを表示させたりイベントをつけたりすることができたりします。今回ご紹介しましたのは一部ですがこんな感じになります。ドキュメントにはshowcaseなども用意されているので、コピペして改良してもよいかもしれません。