diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 8bf15793..d81c11ed 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -2,15 +2,14 @@ import { D3ZoomEvent, zoom, zoomIdentity, ZoomTransform } from 'd3-zoom'; import { select, pointer } from 'd3-selection'; import { clamp } from '../../utils'; import { FlowTransform, TranslateExtent, PanOnScrollMode, KeyCode, RevueFlowStore } from '../../types'; -import { computed, defineComponent, inject, onUpdated, PropType, ref } from 'vue'; +import { defineComponent, inject, PropType, ref, watchPostEffect } from 'vue'; import useKeyPress from '../../hooks/useKeyPress'; import useResizeHandler from '../../hooks/useResizeHandler'; import { RevueFlowHooks } from '../../hooks/RevueFlowHooks'; -import { templateRef, whenever } from '@vueuse/core'; +import { templateRef } from '@vueuse/core'; import { ZoomBehavior } from 'd3'; interface ZoomPaneProps { - selectionKeyPressed: boolean; elementsSelectable?: boolean; zoomOnScroll?: boolean; zoomOnPinch?: boolean; @@ -59,10 +58,10 @@ export default defineComponent({ required: false, default: true }, - selectionKeyPressed: { - type: Boolean as PropType, + selectionKeyCode: { + type: [Number, String] as PropType, required: false, - default: false + default: undefined }, elementsSelectable: { type: Boolean as PropType, @@ -157,21 +156,19 @@ export default defineComponent({ } }); - d3Zoom.on('zoom', (event: D3ZoomEvent) => { - store.transform = [event.transform.x, event.transform.y, event.transform.k]; - hooks.move.trigger(eventToFlowTransform(event.transform)); - }); - - const selectionKeyPressed = computed(() => props.selectionKeyPressed); - whenever(selectionKeyPressed, () => { - if (selectionKeyPressed.value) { + useKeyPress(props.selectionKeyCode, (keyPress) => { + if (keyPress) { d3Zoom.on('zoom', null); + } else { + d3Zoom.on('zoom', (event: D3ZoomEvent) => { + store.transform = [event.transform.x, event.transform.y, event.transform.k]; + hooks.move.trigger(eventToFlowTransform(event.transform)); + }); } }); - const zoomActivationKeyPressed = useKeyPress(props.zoomActivationKeyCode); - whenever(zoomActivationKeyPressed, () => { - if (props.panOnScroll) { + useKeyPress(props.zoomActivationKeyCode, (keyPress) => { + if (props.panOnScroll && keyPress) { store.d3Selection ?.on('wheel', (event: WheelEvent) => { event.preventDefault(); @@ -209,7 +206,10 @@ export default defineComponent({ }); }; + watchPostEffect(() => store.d3Zoom && applyZoomFilter(store.d3Zoom)); + const applyZoomFilter = (d3Zoom: ZoomBehavior) => { + const keyPress = useKeyPress(props.selectionKeyCode); d3Zoom.filter((event: MouseEvent) => { const zoomScroll = props.zoomOnScroll; const pinchZoom = props.zoomOnPinch && event.ctrlKey; @@ -220,7 +220,7 @@ export default defineComponent({ } // during a selection we prevent all other interactions - if (props.selectionKeyPressed) { + if (keyPress.value) { return false; } @@ -267,7 +267,6 @@ export default defineComponent({ }; init(); - onUpdated(() => init()); return () => (
diff --git a/src/hooks/useKeyPress.ts b/src/hooks/useKeyPress.ts index d992e4ca..92c9d018 100644 --- a/src/hooks/useKeyPress.ts +++ b/src/hooks/useKeyPress.ts @@ -1,9 +1,16 @@ -import { ref, Ref } from 'vue'; +import { Ref } from 'vue'; import { KeyCode } from '../types'; -import { onKeyStroke, useEventListener } from '@vueuse/core'; +import { controlledRef, onKeyStroke, useEventListener } from '@vueuse/core'; -export default (keyCode?: KeyCode): Ref => { - const keyPressed = ref(false); +export default (keyCode?: KeyCode, cb?: (keyPress: boolean) => void): Ref => { + const keyPressed = controlledRef(false, { + onBeforeChange(val, oldVal) { + if (val === oldVal) return false; + }, + onChanged() { + if (cb && typeof cb === 'function') cb(keyPressed.value); + } + }); onKeyStroke( (event) => event.key === keyCode || event.keyCode === keyCode, @@ -34,5 +41,7 @@ export default (keyCode?: KeyCode): Ref => { keyPressed.value = false; }); + if (cb && typeof cb === 'function') cb(keyPressed.value); + return keyPressed; };