效果圖
代碼
< 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 = typeisDragging. 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>