-
Notifications
You must be signed in to change notification settings - Fork 3
๐ ๋๋๊ทธ์ค๋๋กญ์ผ๋ก ๋ ธ๋ ๊ฐ ๊ฐ์ ์์ฑ
- ๋ ธ๋ ์์ฑ ๋ก์ง ๊ตฌํํ ๊ฒ์์ ๋๋๊ทธ ์ค ๋๋กญ ์ ์ปค์ ์์น๋ฅผ ๊ณ์ ์ถ์ ํ๊ณ ์๋ค.
- ๊ทธ๋ผ DragEnd์ผ ๋ ๋๋กญ ์ขํ์ ๋ฐ๋ผ ๋ถ๊ธฐ์ฒ๋ฆฌ๋ง ํ๋ฉด ๋์ง ์์๊น?
๊ฐ๋จํ๊ฒ๋ ์ด 2๊ฐ์ ๋ฐฉ๋ฒ์ด ๋ ์ค๋ฅธ๋ค.
[1] drop ์ขํ๋ฅผ ๊ณ์ฐํด์, space์ ๊ทธ๋ ค์ง ๋ ธ๋๋ค์ ๋ฒ์๋ค์ ๊ณ์ฐ ํ ์ํํ์ฌ ๊ฒน์น๋ ๊ฒ์ด ์๋์ง ์๋ณํ๊ธฐ
[2] Konva์ ๋ฐ๋ชจ์ ์๋ hit detection์ ํ์ฉํด์ ๋ ธ๋๋ฅผ ์ฌ๊ฐํ์ผ๋ก ๊ฐ์ธ๊ณ , haveIntersection ๋ฉ์๋ ํ์ฉํ๊ธฐ
์ง๊ด์ ์ผ๋ก ์๊ฐํ๊ธฐ์๋ [1]์ด ํ์ํ๊ณ ์ฐ์ฐํ๋ ๊ณผ์ ์ด ๋ง์ ๊ฒ ๊ฐ์๋ฐ ์ฌ์ค [2]๋ ๋ด๋ถ ๊ตฌํ์ ์ ๋ชจ๋ฅด๊ฒ ๋ค. ๊ตฌํ ๋์ด๋๊ฐ ๊ฐ๋จํ ๊ฒ์ [2]๋ก ์์๋๋ฏ๋ก, [2]๋ก ๋จผ์ ์๋ํด๋ณด์!
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๏ธโฃ ๊ธฐ์กด ๋ ธ๋ ์ฌ์ด์ ๊ฐ์ ์์ฑ์ด ๋ฐ๋ก ์๋๋ ๊ฒ โ
๊ณ์ ์๋ํ๋ค๋ณด๋ ์์ธ์ ์ฐพ์๋ค. ๋๋กญํ ๋ ํ ๊ฐ์ ์๋ง ๊ฒน์น๋ ๊ฒ ์๋๋ผโฆ ๋ค์์ ์์ด ๊ฒน์น ์ ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ค.
- ๋์์ฑ ๋ค์ ์๊ฐํด๋ณด์.
(1) ๋๋กญ ์์น๊ฐ ๋ค์์ ๋ ธ๋์ ์ค์ฒฉ๋๋ฉด ๋ ธ๋ ์์ฑ ๋ง์๋ฒ๋ฆฌ๊ธฐ
(2) ๋ ๋ง์ ์์ญ์ด ๊ฒน์น ๋ ธ๋์ ์ฐ๊ฒฐํด์ฃผ๊ธฐ (์ผ๋ง๋ ๊ฒน์ณค๋์ง ๋น๊ตํ ์ ์์ด์ผ ํจ, ๋ ธ๋์ ์ค์ฌ์ ๊ฑฐ๋ฆฌ๋ ๋น๊ตํ ์ ์์)
์ด๋ค ๋์์ฑ ์ ๊ณ ๋ฅด๋๋ผ๋, ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ค ํ์ง๊ฐ ์์ด์ผ ํ ๊ฒ ๊ฐ๋ค. ์ง๊ธ ์ค์ฒฉ๋๊ณ ์๋ ๋ ธ๋๋ค์ ํ์ํ๊ฑฐ๋, ๋ ๊ฐ๊น์ด (๋๋กญ ์ ์ฐ๊ฒฐ๋ ์์ ์ธ) ๋ ธ๋๋ฅผ ํ์ํ๋ ๊ฒ์ด๋ค.
์ฌ์ฉ์ ๊ฒฝํ์์๋ ์ด๋ค ๊ฒ์ด ๋ ์ข์๊น? Space์ ๋ ธ๋๊ฐ ๋ง์์ง๋ฉด, ์ค์ฒฉ๋ ์ผ์ด ๋ง์์งํ ๋ฐ ์์ฑ ์์ฒด๋ฅผ ๋ง์๋ฒ๋ฆฌ๋ฉด ๊ฐ์ ์์ฑ์ด ๋๋ฌด ์ด๋ ค์์ง ๊ฒ ๊ฐ๋ค. ๋ฐ๋ฉด, ์๋ก์ด ๋ ธ๋๋ฅผ ์์ฑํ๊ณ ์ถ์ ๋ ๊ฐ์ ์์ฑ์ด ๋๋ฌด ์๋๋ฉด ๋น ๊ณต๊ฐ์ ๋๋กญํ์ฌ ๋ ธ๋๋ฅผ ์์ฑํ๋ ๊ฒ๋ ์ด๋ ค์ธ ์๋ ์๋ค. (์๋๋ค,, ํ๋ฉด์กฐ์์ผ๋ก Space ํ๋ฉด์ ์ถ์ํด์ ๋ ธ๋๋ฅผ ์กฐ์ํ๋ฉด ๊ด์ฐฎ์๊น?)
๊ทธ๋ผ ๋ฌด์กฐ๊ฑด ๋ ธ๋๊ฐ ์ค์ฒฉ๋๋ ๊ฒ๋ฟ๋ง ์๋๋ผ, ๋๋๊ทธํ๊ณ ์๋ ์ปค์ ์์น์ ๊ฐ ๋ ธ๋์ ์ค์ฌ์ ์ ๊ฑฐ๋ฆฌ๋ฅผ ํ์์ ์ผ๋ก ๊ตฌํด์ผ ํ ์๋ ์๋ค. [๋ ๋ ธ๋์ ์ค์ฒฉ + ์ผ์ ๋ฒ์ ๋ด์ ๋ค์ด์ผ๋ง ๊ฐ์ ์์ฑ]์ผ๋ก ๊ฐ์ ์์ฑ ์กฐ๊ฑด์ ๊ตฌ์ฒดํํ๋ ๊ฒ์ด๋ค.
- ๋๋๊ทธ๋๊ณ ์๋ ์์น์ ์ค์ฒฉ๋๊ณ ์๋ ๋ ธ๋ ํ์ํด์ฃผ๊ธฐ.
์ผ๋จ ๊ฐ์ ์์ฑ์ด ํธ๋ฆฌ๊ฑฐ๋๋ ์กฐ๊ฑด์ ํ์๋ค์ ์กฐ์ธ์ ๊ตฌํด์ ๋ค์ ์๊ฐํด๋ณด๊ณ , ํ์ฌ ์ค์ฒฉ๋๊ณ ์๋ ๋ ธ๋๋ฅผ ํ์ํด์ฃผ๋ ๋ก์ง๋ถํฐ ๊ตฌํํด๋ณด์.
- ์ผ๋จ 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);
}
- ๐ ํ ๋ ธ์
- ๐ค ๊ทธ๋ผ์ด๋ ๋ฃฐ
- ๐ค๏ธ ๋ฐ์ผ๋ฆฌ ์คํฌ๋ผ
- ๐ ํ์๋ก
- โ๏ธ ๊ทธ๋ฃน ํ๊ณ
- โ๏ธ Git & Github ์ปจ๋ฒค์
- ๐ฏ ์๋น์ค ๊ฐ์
- ๐ฅ๏ธ ์์ด์ดํ๋ ์
- โ๏ธ ์ธํ๋ผ ์ํคํ ์ณ
- ๐๏ธ ํ๋ก๋ํธ ๋ฐฑ๋ก๊ทธ
- ๐จ Canvas ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๋น๊ต์ ๊ณ ๋ฏผ
- ๐ซ CSS, JS ์์ด๋ SVG ๋ชจํ์ ๊ตฌํํ ์ ์๋ค๋
- ๐ฅ CRDT๋ฅผ ํ๋ก์ ํธ์ ์ ์ฉํ๊ธฐ - Yjs ๋ฐ์ดํฐํ์ ์ ์
- ๐ณ CI-CD-๊ฐ์ -๊ฒฝํ-๋ฐ-Dockerโcompose-ํ์ฉ
- ๐ฌ FPS ํ ์คํธ๋ก ์ฑ๋ฅ ์ต์ ํ ๊ณ ๋ฏผ ํด๊ฒฐํ๊ธฐ
- ๐ฉโ๐ Konva.js๋ก ์คํ์ด์ค ์ค ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ
- ๐ค Palette๋ฉ๋ด ์ก๊ฐํ ๊ตฌํ์ฒด์ ๋ํ ๊ฐ๋จํ ๊ณ ๋ฏผ
- ๐งโ๐ป React์์ Y.js๋ฅผ ์ฌ์ฉํ๊ธฐ
- ๐ค React์์ Dialog๋ฅผ ๋งค๋๋ฝ๊ฒ ๊ด๋ฆฌํ๊ธฐ
- ๐ WebRTC, WebSocket, SocketIO ๊ธฐ์ ์ ์ ์ ๊ทผ๊ฑฐ์ ์ด์
- ๐ฅ ๋์ํธ์ง ๋งํฌ๋ค์ด ์๋ํฐ ๊ตฌํ๊ธฐ
- ๐ฑ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์ ์ํ ๋ ธ๋.๊ฐ์ ์กฐ์ ๊ธฐ๋ฅ์ ์ง์ํด๋ณด์
- ๐งฑ ๋ชนํ๋ก๊ทธ๋๋ฐ์ผ๋ก ์ค๊ณํ ๊ธฐ๋ณธ ์ปดํฌ๋ํธ
- ๐จ ๋ฐฑ์๋ MySQL์์ MongoDB๋ก ๊ฐ์ ํ ๊ทผ๊ฑฐ ๋ฐ Redis๋ก ์บ์ฑ์ ํ์ง ์๋ ์ด์
- ๐ช ์ฐ์ฌ๊ณก์ ์ฌํ์ํ Gooey ์ธํฐ๋์
- โจ ์ธํฐ๋์ ๊ตฌํ๊ธฐ: ํ๋, ๊ทธ๋ฆฌ๊ณ ์ด๋