diff --git a/packages/core/src/composables/useResizeHandler.ts b/packages/core/src/composables/useResizeHandler.ts new file mode 100644 index 00000000..1978bd02 --- /dev/null +++ b/packages/core/src/composables/useResizeHandler.ts @@ -0,0 +1,44 @@ +import type { Ref } from 'vue' +import { watchEffect } from 'vue' +import { ErrorCode, VueFlowError, getDimensions } from '../utils' +import { useVueFlow } from './useVueFlow' + +export function useResizeHandler(viewportEl: Ref): void { + const { emits, dimensions } = useVueFlow() + + let resizeObserver: ResizeObserver + + watchEffect((onCleanup) => { + const rendererNode = viewportEl.value + + const updateDimensions = () => { + if (!rendererNode) { + return + } + + const size = getDimensions(rendererNode) + + if (size.width === 0 || size.height === 0) { + emits.error(new VueFlowError(ErrorCode.MISSING_VIEWPORT_DIMENSIONS)) + } + + dimensions.value = size + } + + updateDimensions() + window.addEventListener('resize', updateDimensions) + + if (rendererNode) { + resizeObserver = new ResizeObserver(() => updateDimensions()) + resizeObserver.observe(rendererNode) + } + + onCleanup(() => { + window.removeEventListener('resize', updateDimensions) + + if (resizeObserver && rendererNode) { + resizeObserver.unobserve(rendererNode!) + } + }) + }) +} diff --git a/packages/core/src/container/Viewport/Viewport.vue b/packages/core/src/container/Viewport/Viewport.vue index b574a855..3a9e16d5 100644 --- a/packages/core/src/container/Viewport/Viewport.vue +++ b/packages/core/src/container/Viewport/Viewport.vue @@ -3,12 +3,13 @@ import type { D3ZoomEvent, ZoomTransform } from 'd3-zoom' import { zoom, zoomIdentity } from 'd3-zoom' import { pointer, select } from 'd3-selection' import { onMounted, ref, watch } from 'vue' -import { toRef, useEventListener, useResizeObserver } from '@vueuse/core' +import { toRef } from '@vueuse/core' import type { CoordinateExtent, D3ZoomHandler, ViewportTransform } from '../../types' import { PanOnScrollMode } from '../../types' import { useKeyPress, useVueFlow, useWindow } from '../../composables' -import { ErrorCode, VueFlowError, clamp, getDimensions, isMacOs, warn } from '../../utils' +import { clamp, isMacOs, warn } from '../../utils' import Pane from '../Pane/Pane.vue' +import { useResizeHandler } from '../../composables/useResizeHandler' import Transform from './Transform.vue' const window = useWindow() @@ -19,7 +20,6 @@ const { maxZoom, defaultViewport, translateExtent, - dimensions, zoomActivationKeyCode, selectionKeyCode, panActivationKeyCode, @@ -44,6 +44,8 @@ const { viewportRef, } = useVueFlow() +useResizeHandler(viewportRef) + const isZoomingOrPanning = ref(false) const isPanScrolling = ref(false) @@ -72,10 +74,6 @@ const shouldPanOnScroll = toRef(() => panKeyPressed.value || panOnScroll.value) const isSelecting = toRef(() => selectionKeyPressed.value || (selectionKeyCode.value === true && shouldPanOnDrag.value !== true)) -useResizeObserver(viewportRef, setDimensions) - -useEventListener(window, 'resize', setDimensions) - onMounted(() => { if (!viewportRef.value) { warn('Viewport element is missing') @@ -107,6 +105,8 @@ onMounted(() => { storeD3Selection.value = d3Selection storeD3ZoomHandler.value = d3ZoomHandler as D3ZoomHandler + console.log('d3Zoom', d3Zoom) + viewport.value = { x: constrainedTransform.x, y: constrainedTransform.y, zoom: constrainedTransform.k } d3Zoom.on('start', (event: D3ZoomEvent) => { @@ -369,21 +369,6 @@ function eventToFlowTransform(eventTransform: ZoomTransform): ViewportTransform } } -function setDimensions() { - if (!viewportRef.value) { - return - } - - const { width, height } = getDimensions(viewportRef.value) - - if (width === 0 || height === 0) { - emits.error(new VueFlowError(ErrorCode.MISSING_VIEWPORT_DIMENSIONS)) - } - - dimensions.value.width = width || 500 - dimensions.value.height = height || 500 -} - function isWrappedWithClass(event: Event, className: string | undefined) { return (event.target as Element).closest(`.${className}`) }