我使用优秀的“Neodrag”包制作了一个简单的 REPL,用于拖动组件。
但是,当我添加新节点或调整节点大小时,它们似乎会相互交互。例如,当调整“旧”节点的大小时,新节点彼此偏移,并且其他节点会移动。有没有人有这方面的经验并且能够提供帮助?
https://svelte.dev/playground/a35a7c16caa64842b694b5631d1d7a57?version=5.19.0
谢谢!
代码是:
// globalstate.svelte.js
export 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>
事实证明,所需的所有 div 都是“位置:绝对!重要;”风格。