效果图
代码
< template>
< div style= "width: 100%;height: calc(100vh - 84px)" >
< VueFlow : nodes= "nodes" : edges= "edges" @drop= "onDrop" @dragover= "onDragOver" @dragleave= "onDragLeave" >
< div class = "dropzone-background" >
< Background pattern- color= "#aaa" : gap= "8" : style= "{
backgroundColor: isDragOver ? '#e7f3ff' : 'transparent' ,
transition: 'background-color 0.2s ease' ,
} ">
< / Background>
< div class = "overlay" >
< p v- if = "isDragOver" > Drop here< / p>
< / div>
< / div>
< / VueFlow>
< Panel position= "top-right" class = "process-panel" >
< div class = "description" > You can drag these nodes to the pane. < / div>
< div class = "nodes" >
< div class = "vue-flow__node-input" : draggable= "true" @dragstart= "onDragStart($event, 'input')" > Input Node< / div>
< div class = "vue-flow__node-default" : draggable= "true" @dragstart= "onDragStart($event, 'default')" > Default Node
< / div>
< div class = "vue-flow__node-output" : draggable= "true" @dragstart= "onDragStart($event, 'output')" > Output Node
< / div>
< / div>
< / Panel>
< / div>
< / template>
< script setup name= "Index" >
import { ref} from 'vue'
import { VueFlow, Panel, useVueFlow} from '@vue-flow/core'
import { Background} from '@vue-flow/background'
import { MiniMap} from '@vue-flow/minimap'
const { onConnect, addEdges, addNodes, toObject, screenToFlowCoordinate, onNodesInitialized, updateNode} = useVueFlow ( )
const instance = useVueFlow ( )
const { proxy} = getCurrentInstance ( ) ;
const nodes = ref ( [ ] ) ;
const edges = ref ( [ ] ) ;
const draggedType = ref ( null ) ;
const isDragOver = ref ( false ) ;
const isDragging = ref ( false ) ;
function onDragStart ( event, type ) {
if ( event. dataTransfer) {
event. dataTransfer. setData ( 'application/vueflow' , type)
event. dataTransfer. effectAllowed = 'move'
}
draggedType. value = type
isDragging. value = true
document. addEventListener ( 'drop' , onDragEnd)
}
function onDragOver ( event ) {
event. preventDefault ( )
if ( draggedType. value) {
isDragOver. value = true
if ( event. dataTransfer) {
event. dataTransfer. dropEffect = 'move'
}
}
}
function onDrop ( event ) {
const position = screenToFlowCoordinate ( {
x: event. clientX,
y: event. clientY,
} )
const nodeId = Math. random ( ) + "id" ;
const newNode = {
id: nodeId,
type: draggedType. value,
position,
data: { label: nodeId} ,
}
const { off} = onNodesInitialized ( ( ) => {
updateNode ( nodeId, ( node ) => ( {
position: { x: node. position. x - node. dimensions. width / 2 , y: node. position. y - node. dimensions. height / 2 } ,
} ) )
off ( )
} )
addNodes ( newNode)
}
function onDragLeave ( ) {
isDragOver. value = false
}
function onDragEnd ( ) {
isDragging. value = false
isDragOver. value = false
draggedType. value = null
document. removeEventListener ( 'drop' , onDragEnd)
}
onConnect ( addEdges)
< / script>
< style>
@import '@vue-flow/core/dist/style.css' ;
@import '@vue-flow/core/dist/theme-default.css' ;
. process- panel {
background- color: #EBEEF5 ;
padding: 10 px;
border- radius: 8 px;
box- shadow: 0 0 10 px rgba ( 0 , 0 , 0 , 0.5 ) ;
display: flex;
flex- direction: column;
}
. dropzone- background {
position: relative;
height: 100 % ;
width: 100 %
}
. dropzone- background . overlay {
position: absolute;
top: 0 ;
left: 0 ;
height: 100 % ;
width: 100 % ;
display: flex;
align- items: center;
justify- content: center;
z- index: 1 ;
pointer- events: none
}
< / style>