๐Ÿ”ฅ ์ฃผ์ œ

Vue-Flow์—์„œ Node๋ฅผ Drag & Dropํ•˜์—ฌ ํ™”๋ฉด์— ์ƒˆ๋กœ์šด Node๋ฅผ ์ƒ์„ฑํ•ด ๋ณธ๋‹ค.

๐Ÿ˜Š ๋‚ด์šฉ

๐ŸŒŠ Vue Flow - The customizable Vue3 Flowchart Library

Untitled

์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ์ขŒ์ธก Drawer์—์„œ โ€˜EXAM NODE๋ฅผ Drag & Drop ํ•˜์—ฌ ์šฐ์ธก์˜ Form` ์„ ๊ฐ–๋Š” Node๋ฅผ ํ•˜๋‚˜ ์ƒ์„ฑํ•ด ๋ณด์ž.

<aside> ๐Ÿ’ก Drawer์— ์žˆ๋Š” Node์™€ ์ƒ์„ฑ๋˜๋Š” Node์˜ ํ˜•ํƒœ ๋ฐ ์ƒ๊น€์ƒˆ๋Š” ๋™์ผํ•  ์ˆ˜๋„ ์žˆ์œผ๋‚˜, ๋‹ค๋ฅธ ๋ชจ์Šต์œผ๋กœ ์ƒ์„ฑ๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

</aside>

์šฐ๋ฆฌ๋Š” ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค์— ํ•ด๋‹นํ•˜๋Š” ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ๊ฐ์ข… ์ž…๋ ฅ์„ ๋ฐ›์•„์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— Custom Node๋ฅผ ์ƒ์„ฑํ•  ๊ฒƒ์ด๋‹ค.

Drawer

<script setup>
function onDragStart(event, nodeType) {
  if (event.dataTransfer) {
    event.dataTransfer.setData('application/vueflow', nodeType)
    event.dataTransfer.effectAllowed = 'move'
  }
}
</script>

<template>
  <v-navigation-drawer
      width="244"
    >
    <div class="nodes">
      <div class="vue-flow__node-default" :draggable="true"
      @dragstart="onDragStart($event, 'exam1')">Exam 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>
    </v-navigation-drawer>
</template>

<aside> ๐Ÿ’ก ์—ฌ๊ธฐ์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ์˜ ๋“œ๋ž˜๊ทธ ์‹œ์ž‘ ํ•ธ๋“ค๋Ÿฌ์— nodeType์„ exam1 ์œผ๋กœ ์ „๋‹ฌํ•œ๋‹ค.

</aside>

App - script setup

<script setup>
import ExamNode1 from './components/ExamNode1.vue';
import AppBar from './layouts/default/AppBar.vue'
import LeftDrawer from './layouts/default/LeftDrawer.vue'

import { VueFlow, useVueFlow } from '@vue-flow/core'
import { nextTick, watch } from 'vue'

let id = 0
function getId() {
  return `dndnode_${id++}`
}

const { findNode, onConnect, addEdges, addNodes, project, vueFlowRef } = useVueFlow({
  nodes: [],
})

function onDragOver(event) {
  event.preventDefault()

  if (event.dataTransfer) {
    event.dataTransfer.dropEffect = 'move'
  }
}

onConnect((params) => addEdges(params))

function onDrop(event) {
  const type = event.dataTransfer?.getData('application/vueflow')
  console.log(type)
  const { left, top } = vueFlowRef.value.getBoundingClientRect()

  const position = project({
    x: event.clientX - left,
    y: event.clientY - top,
  })

  const newNode = {
    id: getId(),
    type,
    position,
    label: `${type} node`,
    info: {"foo": "bar"},
  }

  addNodes([newNode])

  // align node position after drop, so it's centered to the mouse
  nextTick(() => {
    const node = findNode(newNode.id)
    const stop = watch(
      () => node.dimensions,
      (dimensions) => {
        if (dimensions.width > 0 && dimensions.height > 0) {
          node.position = { x: node.position.x - node.dimensions.width / 2, y: node.position.y - node.dimensions.height / 2 }
          stop()
        }
      },
      { deep: true, flush: 'post' },
    )
  })
}
</script>

App - template, style