IgrDataChart で軸ラベルをマウスで操作したときに、シリーズの縦棒を強調表示したり、目標ライン(オーバーレイ)を表示したりするには、軸ラベルのマウス イベント(axisLabelMouseEnter / axisLabelMouseLeave / axisLabelMouseDown / axisLabelMouseUp / axisLabelMouseClick)を使います。

IgrDataChart の設定

IgrDataChart に軸ラベルのイベント ハンドラーを設定します。カテゴリ軸(月)と数値軸(売上)を配置し、2 つの縦棒シリーズで isCustomCategoryStyleAllowed を有効にして assigningCategoryStyle イベントを設定します。目標ラインには IgrValueOverlay を使います。IgrDataChart の子要素には null や false を渡せないため、オーバーレイは条件付きレンダリングではなく visibility で表示を切り替えます。

<IgrDataChart
    axisLabelMouseEnter={onLabelEnter}
    axisLabelMouseLeave={onLabelLeave}
    axisLabelMouseDown={onLabelDown}
    axisLabelMouseUp={onLabelUp}
    axisLabelMouseClick={onLabelClick}
    ...>
    <IgrCategoryXAxis name="xAxis" dataSource={salesData} label="month" interval={1} />
    <IgrNumericYAxis name="yAxis" minimumValue={0} ... />
    <IgrColumnSeries
        ref={previousSeriesRef}
        name="previous"
        valueMemberPath="previous"
        isCustomCategoryStyleAllowed
        assigningCategoryStyle={fadeOutsideHighlight}
        ... />
    <IgrColumnSeries
        ref={currentSeriesRef}
        name="current"
        valueMemberPath="current"
        isCustomCategoryStyleAllowed
        assigningCategoryStyle={fadeOutsideHighlight}
        ... />
    <IgrValueOverlay
        name="target"
        axisName="yAxis"
        value={target ?? 0}
        visibility={target === null ? Visibility.Collapsed : Visibility.Visible}
        isAxisAnnotationEnabled
        ... />
</IgrDataChart>

軸ラベル イベントの処理

軸ラベルのイベントは、軸ラベル上でマウスを操作したときに発生します。引数の IgrAxisMouseEventArgs から、e.axis で対象の軸、e.label でラベルの表示文字列、e.axisValue で軸上の値を取得できます。イベントはチャート内のすべての軸で共通のため、e.axis?.name を見て、どの軸のラベルが操作されたかを判別します。

カテゴリ軸ラベルのドラッグで範囲を選択する

月ラベルの axisLabelMouseDown で範囲選択を開始します。ドラッグ中に axisLabelMouseEnter で入ったラベルまで範囲を広げ、axisLabelMouseUp で選択範囲を確定します。ドラッグしていないときは、axisLabelMouseEnter / axisLabelMouseLeave でホバー中の 1 か月だけを強調表示します。ラベルからデータ項目のインデックスを求めるには、e.label で一致する項目を探し、見つからない場合は e.axisValue の値を使います。なお、サンプルでは月ラベル以外の場所でマウスを離した場合にも範囲を確定できるよう、window の pointerup イベントもキャプチャ フェーズで処理しています。

function resolveMonthIndex(e: IgrAxisMouseEventArgs): number {
    const byLabel = salesData.findIndex((d) => d.month === e.label)
    if (byLabel >= 0) return byLabel
    const index = Math.round(e.axisValue)
    return index >= 0 && index < salesData.length ? index : -1
}

const onLabelEnter = useCallback((_s: IgrSeriesViewer, e: IgrAxisMouseEventArgs) => {
    if (e.axis?.name !== 'xAxis') return
    const index = resolveMonthIndex(e)
    if (index < 0) return
    setHoverIndex(index)
    const current = dragRef.current
    if (current !== null && current.end !== index) setDrag({ start: current.start, end: index })
}, [setDrag])

const onLabelLeave = useCallback(() => {
    setHoverIndex(null)
}, [])

const onLabelDown = useCallback((_s: IgrSeriesViewer, e: IgrAxisMouseEventArgs) => {
    if (e.axis?.name !== 'xAxis') return
    const index = resolveMonthIndex(e)
    if (index >= 0) setDrag({ start: index, end: index })
}, [setDrag])

const onLabelUp = useCallback((_s: IgrSeriesViewer, e: IgrAxisMouseEventArgs) => {
    const current = dragRef.current
    if (e.axis?.name !== 'xAxis' || current === null) return
    const index = resolveMonthIndex(e)
    if (index >= 0) dragRef.current = { start: current.start, end: index }
    commitDrag()
}, [commitDrag])

選択範囲のシリーズを強調表示する

強調表示する範囲は、優先順位の高い順に「ドラッグ中の範囲 → 確定した選択範囲 → ホバー中の月」で決めます。範囲が変わったら各シリーズの notifyVisualPropertiesChanged() を呼んで再描画し、assigningCategoryStyle イベントで範囲外の縦棒の e.opacity を下げます。assigningCategoryStyle はチャート側から呼び出されるため、最新の範囲は ref から読みます。

const highlightRef = useRef(highlight)
useEffect(() => {
    highlightRef.current = highlight
    currentSeriesRef.current?.notifyVisualPropertiesChanged()
    previousSeriesRef.current?.notifyVisualPropertiesChanged()
}, [highlight])

const fadeOutsideHighlight = useCallback((_s: IgrCategorySeries, e: IgrAssigningCategoryStyleEventArgs) => {
    const range = highlightRef.current
    if (range && (e.startIndex < range.start || e.startIndex > range.end)) {
        e.opacity = 0.25
    }
}, [])

値軸ラベルのクリックで目標ラインを表示する

数値軸のラベルがクリックされたら、axisLabelMouseClick で e.label の表示文字列(”200″ など書式付きの数値)を数値に変換し、目標値の state に設定します。この値を IgrValueOverlay の value にバインドし、visibility を切り替えて目標ラインを表示します。同じ値をもう一度クリックすると解除します。

function parseAxisNumber(label: string): number | null {
    const value = Number(label.replace(/[^\d.-]/g, ''))
    return label.trim() !== '' && Number.isFinite(value) ? value : null
}

const onLabelClick = useCallback((_s: IgrSeriesViewer, e: IgrAxisMouseEventArgs) => {
    if (e.axis?.name !== 'yAxis') return
    const value = parseAxisNumber(e.label)
    if (value !== null) setTarget((prev) => (prev === value ? null : value))
}, [])

実行結果

月ラベルにマウスを重ねるとその月の縦棒が強調表示され、月ラベルをドラッグすると選択した期間の縦棒だけが強調表示されます。値ラベルをクリックすると、その値の位置に目標ラインが表示されます。

ダウンロード後、以下のコマンドで実行できます。

npm ci
npm run dev
Tagged: