提供helpline组件,未来可能上传npm吧,躺平了.
支持单个节点拖拽,以及多个同时拖拽对齐
<template>
<div class="w-full h-[1px] border-blue-300 fixed border-dashed border-t-[2px] z-50" :style="{
left: '0px',
top: helpLine.y + 'px',
}"></div>
<div class="h-full w-[1px] border-blue-300 fixed border-dashed border-l-[2px] z-50" :style="{
left: helpLine.x + 'px',
top: '0px',
}"></div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { useVueFlow } from '@vue-flow/core'
const {
toObject,
updateNode,
getViewport,
getSelectedNodes,
onNodeDragStart,
onNodeDrag,
onNodeDragStop,
onSelectionDrag,
onSelectionDragStop,
onSelectionDragStart
} = useVueFlow()
const helpLine = ref({ x: -5, y: -5})
let horizontalHelpLines = []
let verticalHelpLines = []
const handleOnDragStart = ()=>{
const { nodes } = toObject()
const selectedNodes = getSelectedNodes.value
const set = new Set(selectedNodes.map(item => item.id))
horizontalHelpLines = []
verticalHelpLines = []
nodes.filter(item => !set.has(item.id))
.map(item => {
horizontalHelpLines.push({
x: item.position.x,
y: item.position.y,
})
verticalHelpLines.push({
x: item.position.x,
y: item.position.y,
})
})
}
onSelectionDragStart(handleOnDragStart)
onNodeDragStart(handleOnDragStart)
const handleOnDragMove = ()=>{
const selectedNodes = getSelectedNodes.value
let { x, y } = selectedNodes[0].position
selectedNodes.forEach(node => {
x = Math.min(x, node.position.x)
y = Math.min(y, node.position.y)
})
let nx = x, ny = y
helpLine.value = { x: -5, y: -5 }
const v = getViewport()
for (let i = 0; i < horizontalHelpLines.length; i++) {
const help = horizontalHelpLines[i]
if (
y < help.y + 20 * v.zoom &&
y > help.y - 20 * v.zoom
) {
helpLine.value.y = help.y * v.zoom + v.y
ny = help.y
break
}
}
for (let i = 0; i < verticalHelpLines.length; i++) {
const help = verticalHelpLines[i]
if (
x < help.x + 20 * v.zoom &&
x > help.x - 20 * v.zoom
) {
helpLine.value.x = help.x * v.zoom + v.x
nx = help.x
break
}
}
selectedNodes.map(item => {
updateNode(item.id, {
position: {
x: item.position.x + (nx - x),
y: item.position.y + (ny - y),
}
})
})
}
onSelectionDrag(handleOnDragMove)
onNodeDrag(handleOnDragMove)
const handleOnDragEnd = ()=>{
helpLine.value = { x: -5, y: -5 }
}
onSelectionDragStop(handleOnDragEnd)
onNodeDragStop(handleOnDragEnd)
</script>
最后在你的fow里面加入这个组件
<template>
<div class="w-full h-full z-50 relative bg-gray-100 translate-x-0" ref="playground">
<VueFlow v-model:nodes="nodes" :edges="edges">
<HelpLine />
</VueFlow>
</div>
一些css的细节可能没仔细调整,如果你发现定位不准确,可能是css配置的原因,注意,translate, fixed这几个的配置。祝你好运