fix(core,additional-components): apply translate extent on pan
Signed-off-by: braks <78412429+bcakmakoglu@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { GraphNode } from '@vue-flow/core'
|
import type { CoordinateExtent, GraphNode } from '@vue-flow/core'
|
||||||
import { getBoundsofRects, getConnectedEdges, getRectOfNodes, useVueFlow } from '@vue-flow/core'
|
import { getBoundsofRects, getConnectedEdges, getRectOfNodes, useVueFlow } from '@vue-flow/core'
|
||||||
import { zoom, zoomIdentity } from 'd3-zoom'
|
import { zoom, zoomIdentity } from 'd3-zoom'
|
||||||
import type { D3ZoomEvent } from 'd3-zoom'
|
import type { D3ZoomEvent } from 'd3-zoom'
|
||||||
@@ -33,7 +33,7 @@ const attrs: Record<string, any> = useAttrs()
|
|||||||
const defaultWidth = 200
|
const defaultWidth = 200
|
||||||
const defaultHeight = 150
|
const defaultHeight = 150
|
||||||
|
|
||||||
const { id, edges, viewport, dimensions, emits, nodes, d3Selection, d3Zoom } = useVueFlow()
|
const { id, edges, viewport, translateExtent, dimensions, emits, nodes, d3Selection, d3Zoom } = useVueFlow()
|
||||||
|
|
||||||
const el = ref<SVGElement>()
|
const el = ref<SVGElement>()
|
||||||
|
|
||||||
@@ -128,9 +128,15 @@ watchEffect(
|
|||||||
y: viewport.value.y - event.sourceEvent.movementY * viewScale.value * Math.max(1, viewport.value.zoom),
|
y: viewport.value.y - event.sourceEvent.movementY * viewScale.value * Math.max(1, viewport.value.zoom),
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextTransform = zoomIdentity.translate(position.x, position.y).scale(viewport.value.zoom)
|
const extent: CoordinateExtent = [
|
||||||
|
[0, 0],
|
||||||
|
[dimensions.value.width, dimensions.value.height],
|
||||||
|
]
|
||||||
|
|
||||||
d3Zoom.value.transform(d3Selection.value, nextTransform)
|
const nextTransform = zoomIdentity.translate(position.x, position.y).scale(viewport.value.zoom)
|
||||||
|
const constrainedTransform = d3Zoom.value.constrain()(nextTransform, extent, translateExtent.value)
|
||||||
|
|
||||||
|
d3Zoom.value.transform(d3Selection.value, constrainedTransform)
|
||||||
}
|
}
|
||||||
|
|
||||||
const zoomAndPanHandler = zoom()
|
const zoomAndPanHandler = zoom()
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import type { D3ZoomEvent, ZoomTransform } from 'd3-zoom'
|
import type { D3ZoomEvent, ZoomTransform } from 'd3-zoom'
|
||||||
import { zoom, zoomIdentity } from 'd3-zoom'
|
import { zoom, zoomIdentity } from 'd3-zoom'
|
||||||
import { pointer, select } from 'd3-selection'
|
import { pointer, select } from 'd3-selection'
|
||||||
import type { ViewpaneTransform } from '../../types'
|
import type { CoordinateExtent, ViewpaneTransform } from '../../types'
|
||||||
import { PanOnScrollMode } from '../../types'
|
import { PanOnScrollMode } from '../../types'
|
||||||
import SelectionPane from '../SelectionPane/SelectionPane.vue'
|
import SelectionPane from '../SelectionPane/SelectionPane.vue'
|
||||||
import Transform from './Transform.vue'
|
import Transform from './Transform.vue'
|
||||||
@@ -40,10 +40,10 @@ let isDragging = $ref(false)
|
|||||||
|
|
||||||
const isConnecting = $computed(() => !!connectionStartHandle)
|
const isConnecting = $computed(() => !!connectionStartHandle)
|
||||||
|
|
||||||
const viewChanged = (prevTransform: ViewpaneTransform, eventTransform: ZoomTransform): boolean =>
|
const viewChanged = (prevViewport: ViewpaneTransform, eventTransform: ZoomTransform): boolean =>
|
||||||
(prevTransform.x !== eventTransform.x && !isNaN(eventTransform.x)) ||
|
(prevViewport.x !== eventTransform.x && !isNaN(eventTransform.x)) ||
|
||||||
(prevTransform.y !== eventTransform.y && !isNaN(eventTransform.y)) ||
|
(prevViewport.y !== eventTransform.y && !isNaN(eventTransform.y)) ||
|
||||||
(prevTransform.zoom !== eventTransform.k && !isNaN(eventTransform.k))
|
(prevViewport.zoom !== eventTransform.k && !isNaN(eventTransform.k))
|
||||||
|
|
||||||
const eventToFlowTransform = (eventTransform: ZoomTransform): ViewpaneTransform => ({
|
const eventToFlowTransform = (eventTransform: ZoomTransform): ViewpaneTransform => ({
|
||||||
x: eventTransform.x,
|
x: eventTransform.x,
|
||||||
@@ -53,11 +53,10 @@ const eventToFlowTransform = (eventTransform: ZoomTransform): ViewpaneTransform
|
|||||||
|
|
||||||
const isWrappedWithClass = (event: Event, className: string | undefined) => (event.target as Element).closest(`.${className}`)
|
const isWrappedWithClass = (event: Event, className: string | undefined) => (event.target as Element).closest(`.${className}`)
|
||||||
|
|
||||||
const clampedZoom = clamp(defaultZoom, minZoom, maxZoom)
|
let prevTransform = $ref<ViewpaneTransform>({
|
||||||
|
x: 0,
|
||||||
let transform = $ref({
|
y: 0,
|
||||||
...clampPosition({ x: defaultPosition[0], y: defaultPosition[1] }, translateExtent),
|
zoom: 0,
|
||||||
zoom: clampedZoom,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -80,12 +79,19 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
const bbox = viewportEl.value.getBoundingClientRect()
|
||||||
const d3Zoom = zoom<HTMLDivElement, any>().scaleExtent([minZoom, maxZoom]).translateExtent(translateExtent)
|
const d3Zoom = zoom<HTMLDivElement, any>().scaleExtent([minZoom, maxZoom]).translateExtent(translateExtent)
|
||||||
const d3Selection = select(viewportEl.value).call(d3Zoom)
|
const d3Selection = select(viewportEl.value).call(d3Zoom)
|
||||||
const d3ZoomHandler = d3Selection.on('wheel.zoom')
|
const d3ZoomHandler = d3Selection.on('wheel.zoom')
|
||||||
|
|
||||||
const updatedTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.zoom)
|
const updatedTransform = zoomIdentity.translate(defaultPosition[0], defaultPosition[1]).scale(defaultZoom)
|
||||||
d3Zoom.transform(d3Selection, updatedTransform)
|
const extent: CoordinateExtent = [
|
||||||
|
[0, 0],
|
||||||
|
[bbox.width, bbox.height],
|
||||||
|
]
|
||||||
|
|
||||||
|
const constrainedTransform = d3Zoom.constrain()(updatedTransform, extent, translateExtent)
|
||||||
|
d3Zoom.transform(d3Selection, constrainedTransform)
|
||||||
|
|
||||||
setState({
|
setState({
|
||||||
d3Zoom,
|
d3Zoom,
|
||||||
@@ -101,7 +107,9 @@ onMounted(() => {
|
|||||||
} else if (!keyPress) {
|
} else if (!keyPress) {
|
||||||
d3Zoom.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
d3Zoom.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
|
||||||
setState({ viewport: { x: event.transform.x, y: event.transform.y, zoom: event.transform.k } })
|
setState({ viewport: { x: event.transform.x, y: event.transform.y, zoom: event.transform.k } })
|
||||||
|
|
||||||
const flowTransform = eventToFlowTransform(event.transform)
|
const flowTransform = eventToFlowTransform(event.transform)
|
||||||
|
|
||||||
emits.move({ event, flowTransform })
|
emits.move({ event, flowTransform })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -124,7 +132,7 @@ onMounted(() => {
|
|||||||
isDragging = true
|
isDragging = true
|
||||||
}
|
}
|
||||||
|
|
||||||
transform = flowTransform
|
prevTransform = flowTransform
|
||||||
|
|
||||||
emits.moveStart({ event, flowTransform })
|
emits.moveStart({ event, flowTransform })
|
||||||
})
|
})
|
||||||
@@ -135,9 +143,11 @@ onMounted(() => {
|
|||||||
isZoomingOrPanning = false
|
isZoomingOrPanning = false
|
||||||
isDragging = false
|
isDragging = false
|
||||||
|
|
||||||
if (viewChanged(transform, event.transform)) {
|
if (viewChanged(prevTransform, event.transform)) {
|
||||||
const flowTransform = eventToFlowTransform(event.transform)
|
const flowTransform = eventToFlowTransform(event.transform)
|
||||||
transform = flowTransform
|
|
||||||
|
prevTransform = flowTransform
|
||||||
|
|
||||||
emits.moveEnd({ event, flowTransform })
|
emits.moveEnd({ event, flowTransform })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user