From 6e2822ab49fd3650e91da81aaa69e375b62874ac Mon Sep 17 00:00:00 2001 From: "Mr.Dr.Professor Patrick" Date: Tue, 12 Nov 2024 15:13:27 +0100 Subject: [PATCH] feat: add chart.events.pointermove property (#9) --- src/components/ChartInner/index.tsx | 30 +++++++++++++++++++---------- src/types/chart/chart.ts | 7 ++++++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/components/ChartInner/index.tsx b/src/components/ChartInner/index.tsx index 9ef62d4..aef8bd5 100644 --- a/src/components/ChartInner/index.tsx +++ b/src/components/ChartInner/index.tsx @@ -107,15 +107,25 @@ export const ChartInner = (props: Props) => { }); const clickHandler = data.chart?.events?.click; + const pointerMoveHandler = data.chart?.events?.pointermove; + React.useEffect(() => { if (clickHandler) { dispatcher.on('click-chart', clickHandler); } + if (pointerMoveHandler) { + dispatcher.on('hover-shape.chart', (...args) => { + const [hoverData, _position, event] = args; + pointerMoveHandler(hoverData, event); + }); + } + return () => { dispatcher.on('click-chart', null); + dispatcher.on('hover-shape.chart', null); }; - }, [dispatcher, clickHandler]); + }, [dispatcher, clickHandler, pointerMoveHandler]); const boundsOffsetTop = chart.margin.top; // We only need to consider the width of the first left axis @@ -128,12 +138,12 @@ export const ChartInner = (props: Props) => { [boundsHeight, boundsWidth], ); - const handleMouseMove: React.MouseEventHandler = (event) => { + const handlePointerMove: React.MouseEventHandler = (event) => { const [pointerX, pointerY] = pointer(event, svgRef.current); const x = pointerX - boundsOffsetLeft; const y = pointerY - boundsOffsetTop; if (isOutsideBounds(x, y)) { - dispatcher.call('hover-shape', {}, undefined); + dispatcher.call('hover-shape', {}, undefined, undefined, event); return; } @@ -141,13 +151,13 @@ export const ChartInner = (props: Props) => { position: [x, y], shapesData, }); - dispatcher.call('hover-shape', event.target, closest, [pointerX, pointerY]); + dispatcher.call('hover-shape', event.target, closest, [pointerX, pointerY], event); }; - const throttledHandleMouseMove = throttle(handleMouseMove, THROTTLE_DELAY); + const throttledHandlePointerMove = throttle(handlePointerMove, THROTTLE_DELAY); - const handleMouseLeave = () => { - throttledHandleMouseMove.cancel(); - dispatcher.call('hover-shape', {}, undefined); + const handlePointerLeave: React.MouseEventHandler = (event) => { + throttledHandlePointerMove.cancel(); + dispatcher.call('hover-shape', {}, undefined, undefined, event); }; const handleChartClick = React.useCallback( @@ -185,8 +195,8 @@ export const ChartInner = (props: Props) => { className={b()} width={width} height={height} - onMouseMove={throttledHandleMouseMove} - onMouseLeave={handleMouseLeave} + onPointerMove={throttledHandlePointerMove} + onPointerLeave={handlePointerLeave} onClick={handleChartClick} > {title && } diff --git a/src/types/chart/chart.ts b/src/types/chart/chart.ts index 6a21743..920286b 100644 --- a/src/types/chart/chart.ts +++ b/src/types/chart/chart.ts @@ -1,3 +1,5 @@ +import type {MeaningfulAny} from '../misc'; + export type ChartMargin = { top: number; right: number; @@ -5,9 +7,12 @@ export type ChartMargin = { left: number; }; +type ChartEventData = {point: MeaningfulAny; series: MeaningfulAny}; + export type ChartOptions = { margin?: Partial<ChartMargin>; events?: { - click?: (data: {point: unknown; series: unknown}, event: PointerEvent) => void; + click?: (data: ChartEventData, event: PointerEvent) => void; + pointermove?: (data: ChartEventData | undefined, event: PointerEvent) => void; }; };