如何使用Svelte5和interact.js拖动克隆

问题描述 投票:0回答:1

我正在使用 interact.js 和 Svelte 5(版本 5.0.0-next.200)来拖动最初位于可滚动 div 内部的元素,并且必须将其放置在该 div 的outside 处。为了完成这项工作,我需要克隆该元素,然后拖动克隆(据我所知,没有办法解决)。

现在,在以前的 Vanilla-js 项目中,我成功地改编了此 stackoverflow-answer 中的 代码 并且一切正常。但是,我无法让它在 Svelte 中工作。

下面是我的代码。我假设错误出现在

interaction.start({ name: 'drag' }, ev.interactable, clone);
中,它无法将拖动操作传递到克隆。

热烈欢迎任何帮助。几天来我一直在为此苦苦挣扎。

<script>
    import interact from 'interactjs';

    const dragElement = (ev) => {
        const el = ev.target;
        let x = (parseFloat(el.getAttribute('data-x')) || 0) + ev.dx;
        let y = (parseFloat(el.getAttribute('data-y')) || 0) + ev.dy;
        el.style.webkitTransform = el.style.transform = `translate(${x}px,${y}px)`;
        el.setAttribute('data-x', x);
        el.setAttribute('data-y', y);
    }

    const makeDraggable = (DRAG) => {
        const draggable = document.querySelector('.draggable');
        interact(draggable)
            .draggable({
                allowFrom: '*',
                inertia: false,
                autoScroll: false,
                modifiers: [
                    interact.modifiers.restrict({
                        restriction: '#outer',
                        endOnly: true
                    })
                ],
                onstart: (ev) => {
                    console.log('DRAG START of ', ev.target);
                },

                onmove: (ev) => {
                    console.log('DRAG MOVE of ', ev.target);
                    dragElement(ev);
                },

                onend: (ev) => {
                    console.log('DRAG END of ', ev.target);
                    DRAG.node.orig.style.opacity = 100; // show original again after drag
                }
            })
            .on('move', (ev) => {
                const el = ev.currentTarget;
                const interaction = ev.interaction;
                console.log('ON.MOVE TRY of ', el);
                if (
                    interaction.pointerIsDown && // Only on active interaction
                    interaction.interacting() // Prevent activation by swiping through element
                ) {
                    // If ORIG then make a clone
                    if (
                        DRAG.active == false && // Create only one clone
                        el.getAttribute('isClone') == 'orig' // Prevent re-cloning clones
                    ) {
                        DRAG.active = true;
                        console.log('CLONING START');

                        // Clone node and set its position
                        let clone = el.cloneNode(true);
                        clone.style.left = el.offsetLeft + 'px';
                        clone.style.top = el.offsetTop + 'px';
                        clone.style.position = 'absolute';

                        clone.setAttribute('isClone', 'clone');
                        clone.style.backgroundColor = 'grey';

                        // Append Clone and start drag interaction
                        document.querySelector('#outer').appendChild(clone);
                        console.log('CLONE IS READY: ', clone);

                        DRAG.node.orig = el;
                        DRAG.node.clone = clone;
                        DRAG.node.orig.style.opacity = 0; // hide original while dragging clone
                        interaction.start({ name: 'drag' }, ev.interactable, clone);

                        // if CLONE then drag
                        // } else if (el.getAttribute('isClone') == 'clone') {
                        //  // console.log('MOVING THE CLONE START');
                        //  // dragElement(ev);
                        // }
                    }
                }
            });
    };

    ///////////////////////////////////////////////////////////////
    // DRAG State
    let DRAG = $state({
        active: false,
        node: {
            orig: undefined,
            clone: undefined
        }
    });

    ///////////////////////////////////////////////////////////////
    // Handle drag
    const handleDrag = () => {
        makeDraggable(DRAG);
    };
</script>

<div id="outer">
    <h1>outer</h1>
    <div id="inner">
        <h1>inner (scrollable)</h1>
        <div class="draggable" isClone="orig" use:handleDrag>Drag me</div>
    </div>
</div>

<style>
    #outer {
        position: absolute;
        background-color: yellow;
        height: 95vh;
        width: 90vw;
    }

    #inner {
        position: absolute;
        height: 400px;
        width: 100%;
        background: lightblue;
        overflow-y: scroll;
    }

    .draggable {
        position: absolute;
        background-color: black;
        color: white;
        height: 500px;
        width: 150px;
    }
</style>
svelte draggable interactjs svelte-5
1个回答
0
投票

interaction.stop();
之前添加
interaction.start(...);
可以让您移动克隆体。

请注意,Svelte 5 对 DOM 结构操作很敏感 - 它已经与某些拖放库不兼容。

© www.soinside.com 2019 - 2024. All rights reserved.