I've made a simple REPL using the excellent "Neodrag" package for dragging components.
However, when I add a new node or resize nodes, they seem to interact with each other. For example, the new nodes are offset from each other and other nodes move when an 'older' node is resized. Does anyone have experience in this and able to help?
https://svelte.dev/playground/a35a7c16caa64842b694b5631d1d7a57?version=5.19.0
Thank you!
The code is:
// globalstate.svelte.jsexport let thestate = $state({ nodes:[ {id:0, x:12, y:13, width:145, height:67, text:"The first one"}, {id:1, x:16, y:20, width:145, height:67, text:"Another node"}, ]})
<!-- Node.svelte --><script> import {thestate} from "./globalstate.svelte.js" import { draggable } from '@neodrag/svelte'; let {id="", x=5, y=5, width=10, height=10, text=""} = $props() let isResizing = false; let initialMouseX, initialMouseY, initialWidth, initialHeight; // Resize logic const startResize = (event) => { isResizing = true; initialMouseX = event.clientX; initialMouseY = event.clientY; initialWidth = thestate.nodes[id].width; initialHeight = thestate.nodes[id].height; document.addEventListener('mousemove', doResize); document.addEventListener('mouseup', stopResize); }; const doResize = (event) => { if (isResizing) { const deltaX = event.clientX - initialMouseX; const deltaY = event.clientY - initialMouseY; thestate.nodes[id].width = initialWidth + deltaX; thestate.nodes[id].height = initialHeight + deltaY; } }; const stopResize = () => { isResizing = false; document.removeEventListener('mousemove', doResize); document.removeEventListener('mouseup', stopResize); };</script><div use:draggable={{ bounds: 'parent', handle: '.handle', position: {x:thestate.nodes[id].x, y:thestate.nodes[id].y}, onDrag: ({ offsetX, offsetY }) => { thestate.nodes[id].x= offsetX; thestate.nodes[id].y= offsetY ; } }} style="min-width:50px; min-height:50px; width:{width}px; height:{height}px; background-color: white; position: relative; border-radius: 8px; padding:3px; margin:3px; transform:translate3d({thestate.nodes[id].x}px, {thestate.nodes[id].y}px, 0px);"><div class="dragContent cancel" style="z-index:100; position:absolute; overflow:auto; width:100%; height:100%; color:black;"><p>{text}</p></div><!-- Drag Handle --><div class="handle" style="width: calc({thestate.nodes[id].width}px + 10px); height: calc({thestate.nodes[id].height}px + 30px);"></div><!-- Resize Handle --><div class="resize-handle" on:mousedown={startResize}></div></div><style> .handle { position: absolute; bottom: -5px; left: -5px; border: 2px dotted #333; border-radius: 8px; cursor: grab; opacity: 0; transition: opacity 0.2s ease; } div:hover > .handle { opacity: 1; cursor: grab; } .resize-handle { position: absolute; bottom: -5px; right: -5px; width: 10px; height: 10px; background-color: blue; cursor: nwse-resize; }</style>
<!-- App.svelte --><script> import {thestate} from "./globalstate.svelte.js" import Node from "./Node.svelte" function addnode(){ thestate.nodes.push({id:thestate.nodes.length, x:10, y:11, width:120, height:130, text:thestate.nodes.length+"here"}) }</script><h2>Example nodes on canvas</h2><button onclick={addnode}>Add node</button><div style="width:500px; height:500px; background-color: lightgray; overflow:auto"> {#each thestate.nodes as node} {#key node.id}<Node {...node}/> {/key} {/each}</div><h2>Debugging</h2><a>{JSON.stringify(thestate)}</a>