Commit 489a4d28 authored by tom's avatar tom

fix issue with point placement after select

parent 3bda45a5
...@@ -18,7 +18,7 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) => ...@@ -18,7 +18,7 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
const borderColor = useToken('colors', 'blue.200'); const borderColor = useToken('colors', 'blue.200');
const ref = React.useRef(null); const ref = React.useRef(null);
const isPressed = React.useRef(false); const isActive = React.useRef(false);
const startX = React.useRef<number>(); const startX = React.useRef<number>();
const endX = React.useRef<number>(); const endX = React.useRef<number>();
...@@ -60,14 +60,14 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) => ...@@ -60,14 +60,14 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
}, [ getIndexByX, onSelect ]); }, [ getIndexByX, onSelect ]);
const cleanUp = React.useCallback(() => { const cleanUp = React.useCallback(() => {
isPressed.current = false; isActive.current = false;
startX.current = undefined; startX.current = undefined;
endX.current = undefined; endX.current = undefined;
d3.select(ref.current).attr('opacity', 0); d3.select(ref.current).attr('opacity', 0);
}, [ ]); }, [ ]);
const handelMouseUp = React.useCallback(() => { const handelMouseUp = React.useCallback(() => {
if (!isPressed.current) { if (!isActive.current) {
return; return;
} }
...@@ -88,11 +88,11 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) => ...@@ -88,11 +88,11 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
anchorD3 anchorD3
.on('mousedown.selectionX', (event: MouseEvent) => { .on('mousedown.selectionX', (event: MouseEvent) => {
const [ x ] = d3.pointer(event, anchorEl); const [ x ] = d3.pointer(event, anchorEl);
isPressed.current = true; isActive.current = true;
startX.current = x; startX.current = x;
}) })
.on('mousemove.selectionX', (event: MouseEvent) => { .on('mousemove.selectionX', (event: MouseEvent) => {
if (isPressed.current) { if (isActive.current) {
const [ x ] = d3.pointer(event, anchorEl); const [ x ] = d3.pointer(event, anchorEl);
startX.current && drawSelection(startX.current, x); startX.current && drawSelection(startX.current, x);
endX.current = x; endX.current = x;
...@@ -101,10 +101,10 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) => ...@@ -101,10 +101,10 @@ const ChartSelectionX = ({ anchorEl, height, scale, data, onSelect }: Props) =>
.on('mouseup.selectionX', handelMouseUp) .on('mouseup.selectionX', handelMouseUp)
.on('touchstart.selectionX', (event: TouchEvent) => { .on('touchstart.selectionX', (event: TouchEvent) => {
const pointers = d3.pointers(event, anchorEl); const pointers = d3.pointers(event, anchorEl);
isPressed.current = pointers.length === 2; isActive.current = pointers.length === 2;
}) })
.on('touchmove.selectionX', (event: TouchEvent) => { .on('touchmove.selectionX', (event: TouchEvent) => {
if (isPressed.current) { if (isActive.current) {
const pointers = d3.pointers(event, anchorEl); const pointers = d3.pointers(event, anchorEl);
if (pointers.length === 2 && Math.abs(pointers[0][0] - pointers[1][0]) > 5) { if (pointers.length === 2 && Math.abs(pointers[0][0] - pointers[1][0]) > 5) {
......
...@@ -32,6 +32,8 @@ const ChartTooltip = ({ chartId, xScale, yScale, width, height, data, anchorEl, ...@@ -32,6 +32,8 @@ const ChartTooltip = ({ chartId, xScale, yScale, width, height, data, anchorEl,
const bgColor = useToken('colors', 'blackAlpha.900'); const bgColor = useToken('colors', 'blackAlpha.900');
const ref = React.useRef(null); const ref = React.useRef(null);
const trackerId = React.useRef<number>();
const isVisible = React.useRef(false);
const drawLine = React.useCallback( const drawLine = React.useCallback(
(x: number) => { (x: number) => {
...@@ -129,55 +131,46 @@ const ChartTooltip = ({ chartId, xScale, yScale, width, height, data, anchorEl, ...@@ -129,55 +131,46 @@ const ChartTooltip = ({ chartId, xScale, yScale, width, height, data, anchorEl,
}, [ drawPoints, drawLine, drawContent ]); }, [ drawPoints, drawLine, drawContent ]);
const showContent = React.useCallback(() => { const showContent = React.useCallback(() => {
d3.select(ref.current).attr('opacity', 1); if (!isVisible.current) {
d3.select(ref.current) d3.select(ref.current).attr('opacity', 1);
.selectAll('.ChartTooltip__point') d3.select(ref.current)
.attr('opacity', 1); .selectAll('.ChartTooltip__point')
.attr('opacity', 1);
isVisible.current = true;
}
}, []); }, []);
const hideContent = React.useCallback(() => { const hideContent = React.useCallback(() => {
d3.select(ref.current).attr('opacity', 0); d3.select(ref.current).attr('opacity', 0);
isVisible.current = false;
}, []); }, []);
const createPointerTracker = React.useCallback((event: PointerEvent, isSubsequentCall?: boolean) => { const createPointerTracker = React.useCallback((event: PointerEvent, isSubsequentCall?: boolean) => {
let isShown = false; let isPressed = event.pointerType === 'mouse' && event.type === 'pointerdown' && !isSubsequentCall;
let isPressed = event.pointerType === 'mouse' && (event.type === 'pointerdown' || event.type === 'pointerenter') && !isSubsequentCall;
if (isPressed) { if (isPressed) {
hideContent(); hideContent();
} }
trackPointer(event, { return trackPointer(event, {
move: (pointer) => { move: (pointer) => {
if (!pointer.point || isPressed) { if (!pointer.point || isPressed) {
return; return;
} }
draw(pointer); draw(pointer);
if (!isShown) { showContent();
showContent();
isShown = true;
}
}, },
out: () => { out: () => {
hideContent(); hideContent();
isShown = false; trackerId.current = undefined;
}, },
end: (tracker) => { end: () => {
hideContent(); hideContent();
const isOutside = tracker.sourceEvent?.offsetX && width && (tracker.sourceEvent.offsetX > width || tracker.sourceEvent.offsetX < 0); trackerId.current = undefined;
if (!isOutside && isPressed) {
window.setTimeout(() => {
createPointerTracker(event, true);
}, 0);
}
isShown = false;
isPressed = false; isPressed = false;
}, },
}); });
}, [ draw, hideContent, showContent, width ]); }, [ draw, hideContent, showContent ]);
React.useEffect(() => { React.useEffect(() => {
const anchorD3 = d3.select(anchorEl); const anchorD3 = d3.select(anchorEl);
...@@ -194,11 +187,22 @@ const ChartTooltip = ({ chartId, xScale, yScale, width, height, data, anchorEl, ...@@ -194,11 +187,22 @@ const ChartTooltip = ({ chartId, xScale, yScale, width, height, data, anchorEl,
} }
}) })
.on('pointerenter.tooltip pointerdown.tooltip', (event: PointerEvent) => { .on('pointerenter.tooltip pointerdown.tooltip', (event: PointerEvent) => {
!isMultiTouch && createPointerTracker(event); if (!isMultiTouch) {
trackerId.current = createPointerTracker(event);
}
})
.on('pointermove.tooltip', (event: PointerEvent) => {
if (event.pointerType === 'mouse' && !isMultiTouch && trackerId.current === undefined) {
trackerId.current = createPointerTracker(event);
}
}); });
return () => { return () => {
anchorD3.on('touchmove.tooltip pointerenter.tooltip pointerdown.tooltip', null); anchorD3.on('touchmove.tooltip pointerenter.tooltip pointerdown.tooltip', null);
trackerId.current && anchorD3.on(
[ 'pointerup', 'pointercancel', 'lostpointercapture', 'pointermove', 'pointerout' ].map((event) => `${ event }.${ trackerId.current }`).join(' '),
null,
);
}; };
}, [ anchorEl, createPointerTracker, draw, hideContent, showContent ]); }, [ anchorEl, createPointerTracker, draw, hideContent, showContent ]);
......
...@@ -14,7 +14,7 @@ export interface PointerOptions { ...@@ -14,7 +14,7 @@ export interface PointerOptions {
end?: (tracker: Pointer) => void; end?: (tracker: Pointer) => void;
} }
export function trackPointer(event: PointerEvent, { start, move, out, end }: PointerOptions) { export function trackPointer(event: PointerEvent, { start, move, out, end }: PointerOptions): number {
const tracker: Pointer = { const tracker: Pointer = {
id: event.pointerId, id: event.pointerId,
point: null, point: null,
...@@ -38,7 +38,7 @@ export function trackPointer(event: PointerEvent, { start, move, out, end }: Poi ...@@ -38,7 +38,7 @@ export function trackPointer(event: PointerEvent, { start, move, out, end }: Poi
const target = sourceEvent.target as Element; const target = sourceEvent.target as Element;
const touches = d3.pointers(sourceEvent, target); const touches = d3.pointers(sourceEvent, target);
// disable current tracker when entering to multi touch mode // disable current tracker when entering multi touch mode
touches.length > 1 && untrack(sourceEvent); touches.length > 1 && untrack(sourceEvent);
}) })
.on(`pointerup.${ id } pointercancel.${ id } lostpointercapture.${ id }`, (sourceEvent: PointerEvent) => { .on(`pointerup.${ id } pointercancel.${ id } lostpointercapture.${ id }`, (sourceEvent: PointerEvent) => {
...@@ -68,5 +68,5 @@ export function trackPointer(event: PointerEvent, { start, move, out, end }: Poi ...@@ -68,5 +68,5 @@ export function trackPointer(event: PointerEvent, { start, move, out, end }: Poi
start?.(tracker); start?.(tracker);
return [ 'pointerup', 'pointercancel', 'lostpointercapture', 'pointermove', 'pointerout' ].map((event) => `${ event }.${ id }`); return id;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment