Skip to content

Commit

Permalink
fix: zoom pan helper not being initialized timely
Browse files Browse the repository at this point in the history
  • Loading branch information
bcakmakoglu committed Oct 21, 2021
1 parent c062601 commit ca2901b
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 47 deletions.
5 changes: 4 additions & 1 deletion examples/Basic/Basic.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ const rfInstance = ref<OnLoadParams | null>(null)
const onElementsRemove = (elementsToRemove: Elements) =>
(elements.value = removeElements(elementsToRemove, elements.value as Elements))
const onConnect = (params: Edge | Connection) => (elements.value = addEdge(params, elements.value as Elements))
const onLoad = (revueFlowInstance: OnLoadParams) => (rfInstance.value = revueFlowInstance)
const onLoad = (revueFlowInstance: OnLoadParams) => {
revueFlowInstance.fitView({ padding: 0.1 })
rfInstance.value = revueFlowInstance
}
const updatePos = () => {
elements.value = elements.value.map((el: FlowElement) => {
Expand Down
14 changes: 6 additions & 8 deletions src/additional-components/Controls/Controls.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@ export interface ControlProps extends HTMLAttributes {
showFitView?: boolean
showInteractive?: boolean
fitViewParams?: FitViewParams
onZoomIn?: () => void
onZoomOut?: () => void
onFitView?: () => void
onInteractiveChange?: (interactiveStatus: boolean) => void
}
const props = withDefaults(defineProps<ControlProps>(), {
showZoom: true,
showFitView: true,
showInteractive: true,
})
// todo define types for events
const emit = defineEmits(['zoom-in', 'zoom-out', 'fit-view', 'interaction-change'])
const store = useStore()
const { zoomIn, zoomOut, fitView } = useZoomPanHelper()
Expand All @@ -34,22 +32,22 @@ const mapClasses = ['vue-flow__controls']
const onZoomInHandler = () => {
zoomIn?.()
props.onZoomIn?.()
emit('zoom-in')
}
const onZoomOutHandler = () => {
zoomOut?.()
props.onZoomOut?.()
emit('zoom-out')
}
const onFitViewHandler = () => {
fitView?.(props.fitViewParams)
props.onFitView?.()
emit('fit-view')
}
const onInteractiveChangeHandler = () => {
store.setInteractive?.(!isInteractive.value)
props.onInteractiveChange?.(!isInteractive.value)
emit('interaction-change', !isInteractive.value)
}
</script>
<template>
Expand Down
26 changes: 10 additions & 16 deletions src/composables/useZoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ import { D3ZoomEvent, zoom, zoomIdentity, ZoomTransform } from 'd3-zoom'
import { pointer, select } from 'd3-selection'
import { Ref } from 'vue'
import { get } from '@vueuse/core'
import { FlowTransform, PanOnScrollMode, Transform, UseZoom, UseZoomOptions } from '~/types'
import { FlowTransform, PanOnScrollMode, UseZoom, UseZoomOptions } from '~/types'
import { clamp } from '~/utils'
import useKeyPress from '~/composables/useKeyPress'
import useHooks from '~/composables/useHooks'
import useStore from '~/composables/useStore'
import { useKeyPress, useHooks, useStore } from '~/composables'

const viewChanged = (prevTransform: FlowTransform, eventTransform: ZoomTransform): boolean =>
prevTransform.x !== eventTransform.x || prevTransform.y !== eventTransform.y || prevTransform.zoom !== eventTransform.k
Expand Down Expand Up @@ -38,12 +36,9 @@ export default (el: Ref<HTMLDivElement>, options: UseZoomOptions): UseZoom => {
const clampedX = clamp(defaultPosition[0], store.translateExtent[0][0], store.translateExtent[1][0])
const clampedY = clamp(defaultPosition[1], store.translateExtent[0][1], store.translateExtent[1][1])
const clampedZoom = clamp(defaultZoom, store.minZoom, store.maxZoom)
const transform = controlledRef<Transform>([clampedX, clampedY, clampedZoom], {
onBeforeChange(val, oldVal) {
if (val === oldVal) return false
},
})
store.transform = transform.value
const transform = ref({ x: clampedX, y: clampedY, zoom: clampedZoom })
biSyncRef(transform, prevTransform)

const d3Zoom = ref(
zoom<HTMLDivElement, any>().scaleExtent([store.minZoom, store.maxZoom]).translateExtent(store.translateExtent),
)
Expand All @@ -60,6 +55,7 @@ export default (el: Ref<HTMLDivElement>, options: UseZoomOptions): UseZoom => {
const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom)
d3z.transform(d3s, updatedTransform)
store.initD3Zoom({ d3Zoom: d3z, d3Selection: d3s, d3ZoomHandler })
store.transform = [updatedTransform.x, updatedTransform.y, updatedTransform.k]

const applyZoomHandlers = () => {
d3z.on('start', (event: D3ZoomEvent<HTMLDivElement, any>) => {
Expand All @@ -85,12 +81,10 @@ export default (el: Ref<HTMLDivElement>, options: UseZoomOptions): UseZoom => {
d3z.on('zoom', null)
} else {
d3z.on('zoom', (event: D3ZoomEvent<HTMLDivElement, any>) => {
transform.value = [
clamp(event.transform.x, store.translateExtent[0][0], store.translateExtent[1][0]),
clamp(event.transform.y, store.translateExtent[0][1], store.translateExtent[1][1]),
clamp(event.transform.k, store.minZoom, store.maxZoom),
]
hooks.move.trigger(eventToFlowTransform(event.transform))
const flowTransform = eventToFlowTransform(event.transform)
prevTransform.value = flowTransform

hooks.move.trigger(flowTransform)
})
}
})
Expand Down
4 changes: 1 addition & 3 deletions src/composables/useZoomPanHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import useStore from '~/composables/useStore'

const DEFAULT_PADDING = 0.1

export default (): UseZoomPanHelper => {
const store = useStore()

export default (store = useStore()): UseZoomPanHelper => {
return {
zoomIn: () => store.d3Selection && store.d3Zoom?.scaleBy(store.d3Selection, 1.2),
zoomOut: () => store.d3Selection && store.d3Zoom?.scaleBy(store.d3Selection, 1 / 1.2),
Expand Down
44 changes: 28 additions & 16 deletions src/container/ZoomPane/ZoomPane.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts" setup>
import { onMounted } from 'vue'
import { KeyCode, PanOnScrollMode } from '~/types'
import { useHooks, useStore, useZoom, useZoomPanHelper } from '~/composables'
import { onLoadGetElements, onLoadProject, onLoadToObject } from '~/utils/graph'
Expand Down Expand Up @@ -34,27 +35,38 @@ const store = useStore()
const hooks = useHooks()
const zoomPaneEl = templateRef<HTMLDivElement>('zoom-pane', null)
const { transform } = useZoom(zoomPaneEl, props)
const { width, height } = useElementBounding(zoomPaneEl)
watch(width, (val) => (store.dimensions.width = val))
watch(height, (val) => (store.dimensions.height = val))
watch(transform, (val) => (store.transform = val))
store.transform = transform.value
const { width, height } = useElementBounding(zoomPaneEl)
store.dimensions = {
width: width.value,
height: height.value,
}
const { zoomIn, zoomOut, zoomTo, transform: setTransform, fitView } = useZoomPanHelper()
hooks.load.trigger({
fitView: (params = { padding: 0.1 }) => fitView(params),
zoomIn,
zoomOut,
zoomTo,
setTransform,
project: onLoadProject(store),
getElements: onLoadGetElements(store),
toObject: onLoadToObject(store),
const { transform } = useZoom(zoomPaneEl, props)
store.transform = [transform.value.x, transform.value.y, transform.value.zoom]
watch(width, (val) => (store.dimensions.width = val))
watch(height, (val) => (store.dimensions.height = val))
watch(transform, (val) => (store.transform = [val.x, val.y, val.zoom]))
onMounted(() => {
const { zoomIn, zoomOut, zoomTo, transform: setTransform, fitView } = useZoomPanHelper(store)
watchOnce(
() => width.value && height.value,
() => {
hooks.load.trigger({
fitView: (params = { padding: 0.1 }) => fitView(params),
zoomIn,
zoomOut,
zoomTo,
setTransform,
project: onLoadProject(store),
getElements: onLoadGetElements(store),
toObject: onLoadToObject(store),
})
},
)
})
</script>
<template>
Expand Down
1 change: 0 additions & 1 deletion src/store/useFlowStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ export default function useFlowStore(preloadedState: FlowState): StoreDefinition
}
},
addSelectedElements(elements) {
console.log(elements)
const selectedElementsArr = Array.isArray(elements) ? elements : [elements]
const selectedElementsUpdated = !isEqual(selectedElementsArr, this.selectedElements)
this.selectedElements = selectedElementsUpdated ? selectedElementsArr : this.selectedElements
Expand Down
4 changes: 2 additions & 2 deletions src/types/composables.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Ref } from 'vue'
import { ElementId, Transform } from './types'
import { ElementId, FlowTransform } from './types'
import { D3Zoom, D3Selection, PanOnScrollMode, KeyCode } from './panel'
import { Connection } from '@/src'

Expand All @@ -20,7 +20,7 @@ export interface UseZoomOptions {
}

export interface UseZoom {
transform: Ref<Transform>
transform: Ref<FlowTransform>
d3Zoom: Ref<D3Zoom>
d3Selection: Ref<D3Selection>
}
Expand Down

1 comment on commit ca2901b

@vercel
Copy link

@vercel vercel bot commented on ca2901b Oct 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.