refactor(vue-flow,nodes): use absolute positions instead of deltas

This commit is contained in:
Braks
2022-05-27 23:36:01 +02:00
parent 660c0bceab
commit cec8f4d77e
8 changed files with 265 additions and 201 deletions
+106
View File
@@ -0,0 +1,106 @@
import type { Ref } from 'vue'
import { clampPosition, isParentSelected } from './graph'
import type { CoordinateExtent, Getters, GraphNode, NodeDragItem, XYPosition } from '~/types'
export function getParentNodePosition(parent?: GraphNode): XYPosition {
return {
x: parent?.computedPosition?.x || 0,
y: parent?.computedPosition?.y || 0,
}
}
export function hasSelector(target: Element, selector: string, node: Ref<Element>): boolean {
let current = target
do {
if (current && current.matches(selector)) return true
else if (current === node.value) return false
current = current.parentElement as Element
} while (current)
return false
}
export function getDragItems(
nodes: GraphNode[],
mousePos: XYPosition,
getNode: Getters['getNode'],
nodeId?: string,
): NodeDragItem[] {
return nodes
.filter((n) => (n.selected || n.id === nodeId) && (!n.parentNode || !isParentSelected(n, getNode)))
.map((n) => ({
id: n.id,
position: n.position,
distance: {
x: mousePos.x - n.position.x,
y: mousePos.y - n.position.y,
},
delta: {
x: 0,
y: 0,
},
extent: n.extent,
parentNode: n.parentNode,
dimensions: n.dimensions,
}))
}
export function getEventHandlerParams({
id,
dragItems,
node,
}: {
id?: string
dragItems: NodeDragItem[]
node: GraphNode
}): [GraphNode, GraphNode[]] {
const extendedDragItems: GraphNode[] = dragItems.map((n) => {
return {
...node,
position: n.position,
computedPosition: {
x: (node.computedPosition?.x || 0) + n.delta.x,
y: (node.computedPosition?.y || 0) + n.delta.y,
z: node.computedPosition.z,
},
}
})
return [id ? extendedDragItems.find((n) => n.id === id)! : extendedDragItems[0], extendedDragItems]
}
export function updatePosition(
dragItem: NodeDragItem,
mousePos: XYPosition,
parent?: GraphNode,
nodeExtent?: CoordinateExtent,
): NodeDragItem {
let currentExtent = dragItem.extent || nodeExtent
let nextPosition = { x: mousePos.x - dragItem.distance.x, y: mousePos.y - dragItem.distance.y }
if (dragItem.extent === 'parent') {
if (dragItem.parentNode && dragItem.dimensions.width && dragItem.dimensions.height) {
currentExtent =
parent?.width && parent?.height
? [
[0, 0],
[parent.dimensions.width - dragItem.dimensions.width, parent.dimensions.height - dragItem.dimensions.height],
]
: currentExtent
} else {
currentExtent = nodeExtent
}
}
nextPosition = currentExtent ? clampPosition(nextPosition, currentExtent as CoordinateExtent) : nextPosition
dragItem.delta = {
x: nextPosition.x - dragItem.position.x,
y: nextPosition.y - dragItem.position.y,
}
dragItem.position = nextPosition
return dragItem
}