Skip to content

๐Ÿ“ ๋“œ๋ž˜๊ทธ์•ค๋“œ๋กญ์œผ๋กœ ๋…ธ๋“œ ๊ฐ„ ๊ฐ„์„  ์ƒ์„ฑ

CatyJazzy edited this page Dec 5, 2024 · 1 revision

๐Ÿค”ย ์ดˆ๊ธฐ ๊ตฌ์ƒ


  • ๋…ธ๋“œ ์ƒ์„ฑ ๋กœ์ง ๊ตฌํ˜„ํ•œ ๊ฒƒ์—์„œ ๋“œ๋ž˜๊ทธ ์•ค ๋“œ๋กญ ์‹œ ์ปค์„œ ์œ„์น˜๋ฅผ ๊ณ„์† ์ถ”์ ํ•˜๊ณ  ์žˆ๋‹ค.
  • ๊ทธ๋Ÿผ DragEnd์ผ ๋•Œ ๋“œ๋กญ ์ขŒํ‘œ์— ๋”ฐ๋ผ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ๋งŒ ํ•˜๋ฉด ๋˜์ง€ ์•Š์„๊นŒ?

๊ฐ„๋‹จํ•˜๊ฒŒ๋Š” ์ด 2๊ฐœ์˜ ๋ฐฉ๋ฒ•์ด ๋– ์˜ค๋ฅธ๋‹ค.

[1] drop ์ขŒํ‘œ๋ฅผ ๊ณ„์‚ฐํ•ด์„œ, space์— ๊ทธ๋ ค์ง„ ๋…ธ๋“œ๋“ค์˜ ๋ฒ”์œ„๋“ค์„ ๊ณ„์‚ฐ ํ›„ ์ˆœํšŒํ•˜์—ฌ ๊ฒน์น˜๋Š” ๊ฒƒ์ด ์žˆ๋Š”์ง€ ์‹๋ณ„ํ•˜๊ธฐ

[2] Konva์˜ ๋ฐ๋ชจ์— ์žˆ๋Š” hit detection์„ ํ™œ์šฉํ•ด์„œ ๋…ธ๋“œ๋ฅผ ์‚ฌ๊ฐํ˜•์œผ๋กœ ๊ฐ์‹ธ๊ณ , haveIntersection ๋ฉ”์†Œ๋“œ ํ™œ์šฉํ•˜๊ธฐ

์ง๊ด€์ ์œผ๋กœ ์ƒ๊ฐํ•˜๊ธฐ์—๋Š” [1]์ด ํƒ์ƒ‰ํ•˜๊ณ  ์—ฐ์‚ฐํ•˜๋Š” ๊ณผ์ •์ด ๋งŽ์„ ๊ฒƒ ๊ฐ™์€๋ฐ ์‚ฌ์‹ค [2]๋„ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์ž˜ ๋ชจ๋ฅด๊ฒ ๋‹ค. ๊ตฌํ˜„ ๋‚œ์ด๋„๊ฐ€ ๊ฐ„๋‹จํ•œ ๊ฒƒ์€ [2]๋กœ ์˜ˆ์ƒ๋˜๋ฏ€๋กœ, [2]๋กœ ๋จผ์ € ์‹œ๋„ํ•ด๋ณด์ž!


๐Ÿย Have Intersection ์‚ฌ์šฉํ•˜๊ธฐ



if (haveIntersection(group.getClientRect(), targetRect)) {
      group.findOne('.fillShape').fill('red');
    } else {
      group.findOne('.fillShape').fill('grey');
    }


Client Rect๊ฐ€ ๋ญ˜๊นŒ?

Konva์˜ ๊ณต์‹๋ฌธ์„œ์—์„œ๋Š” getClientRect()๋ฉ”์†Œ๋“œ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค๋ช…ํ•œ๋‹ค.

Return client rectangle {x, y, width, height} of node. This rectangle also include all styling (strokes, shadows, etc). The purpose of the method is similar to getBoundingClientRect API of the DOM.

ํŠน์ • Konva ๋…ธ๋“œ๊ฐ€ ์ฐจ์ง€ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์˜์—ญ์˜ ํฌ๊ธฐ์™€ ์œ„์น˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋ทฐํฌํŠธ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ธก์ •ํ•˜์—ฌ, ์Šคํƒ€์ผ( stroke, shadow, transform ๋“ฑ)์„ ํฌํ•จํ•œ ์‹ค์ œ ์˜์—ญ์„ ๊ณ„์‚ฐํ•ด์ค€๋‹ค. ๋”ฐ๋ผ์„œ, ๋“œ๋ž˜๊ณ  ๋˜๊ณ  ์žˆ๋Š” GooeyNode์˜ ์ขŒํ‘œ = dragPosition, ํ™”๋ฉด์— ๋ Œ๋”๋ง๋œ ๊ธฐ์กด ๋…ธ๋“œ์˜ ์ขŒํ‘œ = { x: node.x, y: node.y }๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์‰ฝ๊ฒŒ ๊ตฌํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.


์•„๋ž˜์˜ ๋ถ‰์€ ํ…Œ๋‘๋ฆฌ๊ฐ€ getClientRect๋ฅผ ํ†ตํ•ด ํ‘œ์‹œ๋œ Konva ๋…ธ๋“œ์˜ ํฌ๊ธฐ์ด๊ณ , collision์ด ๊ฐ์ง€๋˜์—ˆ์„ ๋•Œ ํ•ด๋‹น ๋„ํ˜•์„ ๋ถ‰์€ ์ƒ‰์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ์˜ˆ์‹œ๋‹ค.

https://konvajs.org/docs/sandbox/Collision_Detection.html



HoneyFlow์— ์ ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

useDragNode์ปค์Šคํ…€ํ›…์— ์žˆ๋Š” dragEnd ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜์— ๋‹ค์Œ์˜ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

function handleDragEnd() {

	// ๋“œ๋ž˜๊ทธ ์ƒํƒœ์—์„œ ์•„๋ž˜์˜ ๋‘ ์ •๋ณด๋ฅผ ์ถ”์ถœ 
	const { ๋“œ๋ž˜๊ทธ์‹œ์ž‘๋…ธ๋“œ, ๋“œ๋ž˜๊ทธ์ค‘์ธ ์ขŒํ‘œ } = dragState;
	
	// ๋ Œ๋”๋ง๋œ node๋ฅผ ์ˆœํšŒํ•˜์—ฌ haveIntersection ๋ฉ”์†Œ๋“œ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰
	const overlapNode = nodes.find ( (node) => {
		
		const result = haveIntersection({ ๋“œ๋ž˜๊ทธ์‹œ์ž‘๋…ธ๋“œ์˜ getClientRect์ •๋ณด }, 
		{ ๋“œ๋ž˜๊ทธ์ค‘์ธ gooey๋…ธ๋“œ์˜ getClientRect์ •๋ณด });
		
		return result; 
	}

	// ๊ฒน์น˜๋Š” ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š”์ง€์— ๋”ฐ๋ผ ๋กœ์ง ์ˆ˜ํ–‰
	overlapNode๊ฐ€ ์žˆ์œผ๋ฉด -> dropPosition null ์ฒ˜๋ฆฌ / ๋‘ ๋…ธ๋“œ์˜ ๊ฐ„์„ ์„ ์ƒ์„ฑ
	์—†์œผ๋ฉด -> ์ƒˆ๋กœ์šด ๋…ธ๋“œ ์ƒ์„ฑ ๋กœ์ง
} 

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด 1์ฐจ์ ์œผ๋กœ๋Š” ์ž˜ ์ž‘๋™ํ•˜๋Š”๋ฐ, ์—ฃ์ง€์ผ€์ด์Šค์™€ ์˜์ƒ์—์„œ๋„ ๋ณด์ด๋Š” ๋ฒ„๊ทธ๋ฅผ ์ƒ๊ฐํ•ด๋ด์•ผ ํ•œ๋‹ค.

  • ์ž๊ธฐ ์ž์‹ ์œผ๋กœ ์žฌ๊ท€์ ์œผ๋กœ ๋“œ๋กญํ–ˆ์„ ๋•Œ ๊ฐ„์„ ์ด ์ถ”๊ฐ€๋˜๋Š”์ง€?
  • ์ด๋ฏธ ๊ฐ„์„ ์ด ํ‘œ์‹œ๋˜์–ด์žˆ๋Š” ๋‘ ๋…ธ๋“œ ์‚ฌ์ด๋ฅผ ๋“œ๋ž˜๊ทธ&๋“œ๋กญํ–ˆ์„ ๋•Œ, ๋“œ๋ž˜๊ทธ์‹œ์ž‘-๋“œ๋กญํ•œ ์ˆœ์„œ๊ฐ€ ๋‹ฌ๋ผ์ง€๋ฉด ์ƒˆ๋กœ์šด ๊ฐ„์„ ์œผ๋กœ ๊ฐ„์ฃผ๋จ
  • (+) ๋‹ค๋ฅธ ๋…ธ๋“œ์™€ ์ผ์ • ๋ฒ”์œ„์—์„œ ๊ฐ€๊นŒ์›Œ์ง€๋ฉด Gooey Connection ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ด ๋ณธ๋ž˜ ๊ธฐํš์— ๋” ๊ฐ€๊นŒ์›€

แ„€แ…กแ†ซแ„‰แ…ฅแ†ซแ„‰แ…ขแ†ผแ„‰แ…ฅแ†ผ-แ„‡แ…ฅแ„€แ…ณ1.gif

๐Ÿย Bug ์žก๊ธฐโ€ฆใ… ใ… 


์œ„์˜ ๋ฆฌ์ŠคํŒ…ํ•œ ์ด์Šˆ๋“ค ์ค‘ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์„ ์ •ํ•ด๋ณด์ž.

  1. ๊ธฐ์กด ๋…ธ๋“œ ์‚ฌ์ด์˜ ๊ฐ„์„  ์ƒ์„ฑ์ด ๋ฐ”๋กœ ์•ˆ๋˜๋Š” ๊ฒƒ โœ…
  2. ์ด๋ฏธ ๊ฐ„์„ ์ด ์žˆ๋Š” ๋‘ ๋…ธ๋“œ ์‚ฌ์ด์— ์ƒˆ๋กœ์šด ๊ฐ„์„ ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ โœ…
  3. ์ž๊ธฐ ์ž์‹ ์œผ๋กœ ๋“œ๋กญํ–ˆ์„ ๋•Œ์˜ ๊ฐ„์„ ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ โœ…


1๏ธโƒฃ ๊ธฐ์กด ๋…ธ๋“œ ์‚ฌ์ด์˜ ๊ฐ„์„  ์ƒ์„ฑ์ด ๋ฐ”๋กœ ์•ˆ๋˜๋Š” ๊ฒƒ โœ…

๊ณ„์† ์‹œ๋„ํ•˜๋‹ค๋ณด๋‹ˆ ์›์ธ์„ ์ฐพ์•˜๋‹ค. ๋“œ๋กญํ•  ๋•Œ ํ•œ ๊ฐœ์˜ ์›๋งŒ ๊ฒน์น˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผโ€ฆ ๋‹ค์ˆ˜์˜ ์›์ด ๊ฒน์น  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋‹ค.


  1. ๋Œ€์‘์ฑ…๋“ค์„ ์ƒ๊ฐํ•ด๋ณด์ž.

(1) ๋“œ๋กญ ์œ„์น˜๊ฐ€ ๋‹ค์ˆ˜์˜ ๋…ธ๋“œ์™€ ์ค‘์ฒฉ๋˜๋ฉด ๋…ธ๋“œ ์ƒ์„ฑ ๋ง‰์•„๋ฒ„๋ฆฌ๊ธฐ

(2) ๋” ๋งŽ์€ ์˜์—ญ์ด ๊ฒน์นœ ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐํ•ด์ฃผ๊ธฐ (์–ผ๋งˆ๋‚˜ ๊ฒน์ณค๋Š”์ง€ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ, ๋…ธ๋“œ์˜ ์ค‘์‹ฌ์  ๊ฑฐ๋ฆฌ๋„ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Œ)

์–ด๋–ค ๋Œ€์‘์ฑ…์„ ๊ณ ๋ฅด๋”๋ผ๋„, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ํ‘œ์ง€๊ฐ€ ์žˆ์–ด์•ผ ํ•  ๊ฒƒ ๊ฐ™๋‹ค. ์ง€๊ธˆ ์ค‘์ฒฉ๋˜๊ณ  ์žˆ๋Š” ๋…ธ๋“œ๋“ค์„ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜, ๋” ๊ฐ€๊นŒ์šด (๋“œ๋กญ ์‹œ ์—ฐ๊ฒฐ๋  ์˜ˆ์ •์ธ) ๋…ธ๋“œ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์ด๋‹ค.


์‚ฌ์šฉ์ž ๊ฒฝํ—˜์—์„œ๋Š” ์–ด๋–ค ๊ฒƒ์ด ๋” ์ข‹์„๊นŒ? Space์— ๋…ธ๋“œ๊ฐ€ ๋งŽ์•„์ง€๋ฉด, ์ค‘์ฒฉ๋  ์ผ์ด ๋งŽ์•„์งˆํ…๋ฐ ์ƒ์„ฑ ์ž์ฒด๋ฅผ ๋ง‰์•„๋ฒ„๋ฆฌ๋ฉด ๊ฐ„์„  ์ƒ์„ฑ์ด ๋„ˆ๋ฌด ์–ด๋ ค์›Œ์งˆ ๊ฒƒ ๊ฐ™๋‹ค. ๋ฐ˜๋ฉด, ์ƒˆ๋กœ์šด ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹ถ์„ ๋•Œ ๊ฐ„์„  ์ƒ์„ฑ์ด ๋„ˆ๋ฌด ์ž˜๋˜๋ฉด ๋นˆ ๊ณต๊ฐ„์— ๋“œ๋กญํ•˜์—ฌ ๋…ธ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๋„ ์–ด๋ ค์šธ ์ˆ˜๋„ ์žˆ๋‹ค. (์•„๋‹ˆ๋‹ค,, ํ™”๋ฉด์กฐ์ž‘์œผ๋กœ Space ํ™”๋ฉด์„ ์ถ•์†Œํ•ด์„œ ๋…ธ๋“œ๋ฅผ ์กฐ์ž‘ํ•˜๋ฉด ๊ดœ์ฐฎ์„๊นŒ?)


๊ทธ๋Ÿผ ๋ฌด์กฐ๊ฑด ๋…ธ๋“œ๊ฐ€ ์ค‘์ฒฉ๋˜๋Š” ๊ฒƒ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๋“œ๋ž˜๊ทธํ•˜๊ณ  ์žˆ๋Š” ์ปค์„œ ์œ„์น˜์™€ ๊ฐ ๋…ธ๋“œ์˜ ์ค‘์‹ฌ์ ์˜ ๊ฑฐ๋ฆฌ๋ฅผ ํ•„์ˆ˜์ ์œผ๋กœ ๊ตฌํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. [๋‘ ๋…ธ๋“œ์˜ ์ค‘์ฒฉ + ์ผ์ • ๋ฒ”์œ„ ๋‚ด์— ๋“ค์–ด์•ผ๋งŒ ๊ฐ„์„  ์ƒ์„ฑ]์œผ๋กœ ๊ฐ„์„  ์ƒ์„ฑ ์กฐ๊ฑด์„ ๊ตฌ์ฒดํ™”ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.


  1. ๋“œ๋ž˜๊ทธ๋˜๊ณ  ์žˆ๋Š” ์œ„์น˜์— ์ค‘์ฒฉ๋˜๊ณ  ์žˆ๋Š” ๋…ธ๋“œ ํ‘œ์‹œํ•ด์ฃผ๊ธฐ.

์ผ๋‹จ ๊ฐ„์„  ์ƒ์„ฑ์ด ํŠธ๋ฆฌ๊ฑฐ๋˜๋Š” ์กฐ๊ฑด์€ ํŒ€์›๋“ค์˜ ์กฐ์–ธ์„ ๊ตฌํ•ด์„œ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๊ณ , ํ˜„์žฌ ์ค‘์ฒฉ๋˜๊ณ  ์žˆ๋Š” ๋…ธ๋“œ๋ฅผ ํ‘œ์‹œํ•ด์ฃผ๋Š” ๋กœ์ง๋ถ€ํ„ฐ ๊ตฌํ˜„ํ•ด๋ณด์ž.

  • ์ผ๋‹จ nodes๋ฐ์ดํ„ฐ, Node ์ปดํฌ๋„ŒํŠธ๋Š” ๋ชจ๋‘ SpaceView ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‹ค๋ค„์ง„๋‹ค.
  • ๋‹ค๋ฅธ ์ปค์Šคํ…€ํ›…์—์„œ ๊ด€๋ฆฌํ•˜์—ฌ node ๋ฐ์ดํ„ฐ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ทธ ์ƒํƒœ๋ฅผ useDragNode ์ปค์Šคํ…€ํ›…์—์„œ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๊ทธ๋Ÿผ ๋ฐ˜๋Œ€๋กœ useDragNode์— ์ •์˜๋˜์–ด์žˆ๋Š” ๋“œ๋กญ ํ•ธ๋“ค๋Ÿฌ ํ•จ์ˆ˜์—์„œ ๋…ธ๋“œ์˜ ์Šคํƒ€์ผ๋ง์„ ๋ฐ”๊พธ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

nodes ๋ฐ์ดํ„ฐ ์ƒํƒœ๋ฅผ ๋‹ค๋ฃจ๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ›์•„์„œ ํ™œ์šฉํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ โ€ฆ ๋ฐ์ดํ„ฐ ์•ˆ์—๋Š” ์Šคํƒ€์ผ๋ง ๊ด€๋ จ๋œ ๋‚ด์šฉ์„ ๋‹ค๋ฃจ์ง€ ์•Š๋Š”๋‹ค. ๋‹น์žฅ ๋– ์˜ค๋ฅด๋Š” ์ตœ์„ ์˜ ๋ฐฉ์‹์€ ๋“œ๋ž˜๊ทธ ์ค‘์ธ ํŠน์ • ์ƒํ™ฉ์ผ ๋•Œ๋งŒ GooeyNode ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ, ๊ฐ„์„  ์ƒ์„ฑํ•˜๊ณ ์ž ํ•˜๋Š” ์ค‘์ฒฉ๋œ ๋…ธ๋“œ๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ indicator ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.



2๏ธโƒฃ ์ด๋ฏธ ๊ฐ„์„ ์ด ์žˆ๋Š” ๋‘ ๋…ธ๋“œ ์‚ฌ์ด์— ์ƒˆ๋กœ์šด ๊ฐ„์„ ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ โœ…

์ด๊ฑด ๊ฐ„์„ ์ด ์ƒ์„ฑ๋˜๋Š” ๋กœ์ง์—์„œ ๊ฒ€์‚ฌํ•˜๋Š” ๊ฒƒ์ด ์ž์—ฐ์Šค๋Ÿฝ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ์ผ๋‹จ dragEndํ•ธ๋“ค๋Ÿฌ์—์„œ๋Š” ๊ทธ๋Œ€๋กœ createEdgeํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

๋Œ€์‹  createEdgeํ•จ์ˆ˜์— ์ด๋ฏธ ํฌํ•จ๋œ ๊ฐ„์„ ์ธ์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ๊ณผ์ •์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด๋•Œ (from: A, to: B), (from: B, to: A) ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋Š” ๋‘ ๋…ธ๋“œ์˜ ์ˆœ์„œ๊ฐ€ ๋‹ฌ๋ผ๋„ ๊ฐ™์€ ๊ฐ„์„ ์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ์ˆœ์„œ๊ฐ€ ๋ฐ˜๋Œ€์ผ ๋•Œ๋„ ์ฒดํฌํ•œ๋‹ค.

 const isSameEdgeExist = edges.some(
        (edge) =>
          (edge.from.id === toNode.id && edge.to.id === fromNode.id) ||
          (edge.from.id === fromNode.id && edge.to.id === toNode.id),
      );

      if (isSameEdgeExist) return;


3๏ธโƒฃ ์ž๊ธฐ ์ž์‹ ์œผ๋กœ ๋“œ๋กญํ–ˆ์„ ๋•Œ์˜ ๊ฐ„์„ ์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ โœ…

ํฌ๊ฐœ์ง„ ๋…ธ๋“œ์˜ Id๊ฐ€ ๋“œ๋ž˜๊ทธ๊ฐ€ ์‹œ์ž‘๋œ ๋…ธ๋“œ Id์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ๋•Œ๋งŒ ๊ฐ„์„ ์ด ์ƒ์„ฑ๋˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.

 if (overlapNode && **overlapNode.id !== startNode.id**) {
      setDropPosition(null);
      spaceActions.createEdge(startNode, overlapNode);
    }

TEAM

DOCS

DEV-NOTES

PRESENTATION

Clone this wiki locally