update: Remove effect watcher from zoom pane

* Add zoom after initialization instead of applying it after every effect watcher call
This commit is contained in:
Braks
2021-08-17 19:44:33 +02:00
parent 23c5d2415c
commit 8d8a4a3d1e
+76 -82
View File
@@ -2,11 +2,12 @@ import { D3ZoomEvent, zoom, zoomIdentity, ZoomTransform } from 'd3-zoom';
import { select, pointer } from 'd3-selection'; import { select, pointer } from 'd3-selection';
import { clamp } from '../../utils'; import { clamp } from '../../utils';
import { FlowTransform, TranslateExtent, PanOnScrollMode, KeyCode, RevueFlowStore } from '../../types'; import { FlowTransform, TranslateExtent, PanOnScrollMode, KeyCode, RevueFlowStore } from '../../types';
import { defineComponent, inject, PropType, ref, watchEffect } from 'vue'; import { computed, defineComponent, inject, PropType, ref } from 'vue';
import useKeyPress from '../../hooks/useKeyPress'; import useKeyPress from '../../hooks/useKeyPress';
import useResizeHandler from '../../hooks/useResizeHandler'; import useResizeHandler from '../../hooks/useResizeHandler';
import { RevueFlowHooks } from '../../hooks/RevueFlowHooks'; import { RevueFlowHooks } from '../../hooks/RevueFlowHooks';
import { templateRef, whenever } from '@vueuse/core'; import { templateRef, whenever } from '@vueuse/core';
import { ZoomBehavior } from 'd3';
interface ZoomPaneProps { interface ZoomPaneProps {
selectionKeyPressed: boolean; selectionKeyPressed: boolean;
@@ -131,6 +132,8 @@ export default defineComponent({
// we need to pass transform because zoom handler is not registered when we set the initial transform // we need to pass transform because zoom handler is not registered when we set the initial transform
transform: [clampedX, clampedY, clampedZoom] transform: [clampedX, clampedY, clampedZoom]
}); });
applyZoomHandlers(d3ZoomInstance);
applyZoomFilter(d3ZoomInstance);
} }
}); });
@@ -172,105 +175,96 @@ export default defineComponent({
} }
}); });
watchEffect(() => { const applyZoomHandlers = (d3Zoom: ZoomBehavior<Element, unknown>) => {
if (store.d3Zoom) { d3Zoom.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => {
if (props.selectionKeyPressed) { if (viewChanged(prevTransform.value, event.transform)) {
store.d3Zoom.on('zoom', null); const flowTransform = eventToFlowTransform(event.transform);
} else { prevTransform.value = flowTransform;
store.d3Zoom.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
store.transform = [event.transform.x, event.transform.y, event.transform.k]; hooks.moveStart.trigger(flowTransform);
hooks.move.trigger(eventToFlowTransform(event.transform));
});
} }
} });
});
watchEffect(() => { d3Zoom.on('end', (event: D3ZoomEvent<HTMLDivElement, any>) => {
if (store.d3Zoom) { if (viewChanged(prevTransform.value, event.transform)) {
store.d3Zoom.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => { const flowTransform = eventToFlowTransform(event.transform);
if (viewChanged(prevTransform.value, event.transform)) { prevTransform.value = flowTransform;
const flowTransform = eventToFlowTransform(event.transform);
prevTransform.value = flowTransform;
hooks.moveStart.trigger(flowTransform); hooks.moveEnd.trigger(flowTransform);
} }
}); });
}
});
watchEffect(() => { d3Zoom.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
if (store.d3Zoom) { store.transform = [event.transform.x, event.transform.y, event.transform.k];
store.d3Zoom.on('end', (event: D3ZoomEvent<HTMLDivElement, any>) => { hooks.move.trigger(eventToFlowTransform(event.transform));
if (viewChanged(prevTransform.value, event.transform)) { });
const flowTransform = eventToFlowTransform(event.transform);
prevTransform.value = flowTransform;
hooks.moveEnd.trigger(flowTransform); const selectionKeyPressed = computed(() => props.selectionKeyPressed);
} whenever(selectionKeyPressed, () => {
}); if (selectionKeyPressed.value) {
} d3Zoom.on('zoom', null);
}); }
});
};
watchEffect(() => { const applyZoomFilter = (d3Zoom: ZoomBehavior<Element, unknown>) => {
if (store.d3Zoom) { d3Zoom.filter((event: MouseEvent) => {
store.d3Zoom.filter((event: MouseEvent) => { const zoomScroll = props.zoomOnScroll;
const zoomScroll = props.zoomOnScroll; const pinchZoom = props.zoomOnPinch && event.ctrlKey;
const pinchZoom = props.zoomOnPinch && event.ctrlKey;
// if all interactions are disabled, we prevent all zoom events // if all interactions are disabled, we prevent all zoom events
if (!props.paneMoveable && !zoomScroll && !props.panOnScroll && !props.zoomOnDoubleClick && !props.zoomOnPinch) { if (!props.paneMoveable && !zoomScroll && !props.panOnScroll && !props.zoomOnDoubleClick && !props.zoomOnPinch) {
return false; return false;
} }
// during a selection we prevent all other interactions // during a selection we prevent all other interactions
if (props.selectionKeyPressed) { if (props.selectionKeyPressed) {
return false; return false;
} }
// if zoom on double click is disabled, we prevent the double click event // if zoom on double click is disabled, we prevent the double click event
if (!props.zoomOnDoubleClick && event.type === 'dblclick') { if (!props.zoomOnDoubleClick && event.type === 'dblclick') {
return false; return false;
} }
if ((event.target as Element).closest('.nowheel') && event.type === 'wheel') { if ((event.target as Element).closest('.nowheel') && event.type === 'wheel') {
return false; return false;
} }
// when the target element is a node, we still allow zooming // when the target element is a node, we still allow zooming
if ( if (
((event.target as Element).closest('.revue-flow__node') || (event.target as Element).closest('.revue-flow__edge')) && ((event.target as Element).closest('.revue-flow__node') || (event.target as Element).closest('.revue-flow__edge')) &&
event.type !== 'wheel' event.type !== 'wheel'
) { ) {
return false; return false;
} }
// when the target element is a node selection, we still allow zooming // when the target element is a node selection, we still allow zooming
if ((event.target as Element).closest('.revue-flow__nodesselection') && event.type !== 'wheel') { if ((event.target as Element).closest('.revue-flow__nodesselection') && event.type !== 'wheel') {
return false; return false;
} }
if (!props.zoomOnPinch && event.ctrlKey && event.type === 'wheel') { if (!props.zoomOnPinch && event.ctrlKey && event.type === 'wheel') {
return false; return false;
} }
// when there is no scroll handling enabled, we prevent all wheel events // when there is no scroll handling enabled, we prevent all wheel events
if (!zoomScroll && !props.panOnScroll && !pinchZoom && event.type === 'wheel') { if (!zoomScroll && !props.panOnScroll && !pinchZoom && event.type === 'wheel') {
return false; return false;
} }
// if the pane is not movable, we prevent dragging it with mousestart or touchstart // if the pane is not movable, we prevent dragging it with mousestart or touchstart
if (!props.paneMoveable && (event.type === 'mousedown' || event.type === 'touchstart')) { if (!props.paneMoveable && (event.type === 'mousedown' || event.type === 'touchstart')) {
return false; return false;
} }
// default filter for d3-zoom // default filter for d3-zoom
return (!event.ctrlKey || event.type === 'wheel') && !event.button; return (!event.ctrlKey || event.type === 'wheel') && !event.button;
}); });
} };
});
return () => ( return () => (
<div class="revue-flow__renderer revue-flow__zoompane" ref="zoom-pane"> <div ref="zoom-pane" class="revue-flow__renderer revue-flow__zoompane">
{slots.default ? slots.default() : ''} {slots.default ? slots.default() : ''}
</div> </div>
); );