You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

拖拽元素放置错误时恢复原位置的HTML+JS技术问题

拖拽元素的归位与隐藏需求实现

我基于一段现有代码做了修改,需要实现以下两个核心需求:

  • 拖拽圆形按钮时,元素从初始位置隐藏,明确提示正在移动
  • 若将元素放置到错误位置,自动恢复至初始位置

现有HTML代码

<div id="bracelet">
    <div id="div1-1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <div id="div1-2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <div id="div1-3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
</div>
<br/><br/><br/><br/><br/>
<div id="div2" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag1" src="http://upload.wikimedia.org/wikipedia/commons/4/4f/Button-Red.svg" ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div3" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag2" src="http://upload.wikimedia.org/wikipedia/commons/a/a8/Button-Blue.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div4" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag3" src="http://upload.wikimedia.org/wikipedia/commons/c/ca/Button-Lightblue.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div5" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag4" src="http://upload.wikimedia.org/wikipedia/commons/b/ba/Button-Purple.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div6" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag5" src="http://upload.wikimedia.org/wikipedia/commons/6/68/Button-Orange.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div7" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag6" src="http://upload.wikimedia.org/wikipedia/commons/d/dc/Button-Green.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div8" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag7" src="http://upload.wikimedia.org/wikipedia/commons/4/4f/Button-Red.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div9" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag8" src="http://upload.wikimedia.org/wikipedia/commons/a/a8/Button-Blue.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div10" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag9" src="http://upload.wikimedia.org/wikipedia/commons/c/ca/Button-Lightblue.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div11" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag10" src="http://upload.wikimedia.org/wikipedia/commons/b/ba/Button-Purple.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div12" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag11" src="http://upload.wikimedia.org/wikipedia/commons/6/68/Button-Orange.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>
<div id="div13" class="drop" ondrop="drop(event)" ondragover="allowDrop(event)">
    <img id="drag12" src="http://upload.wikimedia.org/wikipedia/commons/d/dc/Button-Green.svg"  ondragend="dragEnd(event)" draggable="true" ondragstart="drag(event)" width="50" height="50">
</div>

现有JS代码

function allowDrop(ev) {
    ev.preventDefault();
}

function drag(ev) {
    var el = ev.target;
    var parent = el.getAttribute("data-parent");
    
    if(!parent){
        el.setAttribute("data-parent", el.parentNode.id);
    }
    
    ev.dataTransfer.setData("Text", el.id);
    
    setTimeout(() => {
        ev.target.classList.add('hide'); // 拖拽时隐藏初始位置元素,需在CSS中定义.hide类
    }, 0);
}

function drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("Text");
    ev.target.appendChild(document.getElementById(data)); 
    
    ev.target.classList.remove('drag-over');
    
    const id = ev.dataTransfer.getData('text/plain');
    const draggable = document.getElementById(id);
    ev.target.appendChild(draggable);
    draggable.classList.remove('hide'); 
}

function dragEnd(ev){
    if(ev.dataTransfer.dropEffect == "none"){
         var parent = document.getElementById(ev.target.getAttribute("data-parent"));
        parent.appendChild(ev.target);
    }
}

修正后的完整实现

1. 添加必要CSS

.hide {
    display: none;
}
/* 可选:给放置区域添加样式,方便识别 */
#bracelet div {
    width: 60px;
    height: 60px;
    border: 2px dashed #ccc;
    display: inline-block;
    margin: 0 10px;
}
.drop {
    display: inline-block;
    margin: 0 5px;
}

2. 修正JS逻辑

function allowDrop(ev) {
    ev.preventDefault();
}

function drag(ev) {
    const el = ev.target;
    // 存储初始父容器ID,仅第一次拖拽时设置
    if (!el.getAttribute("data-parent")) {
        el.setAttribute("data-parent", el.parentNode.id);
    }
    ev.dataTransfer.setData("Text", el.id);
    // 延迟隐藏,确保拖拽事件触发后隐藏初始位置元素
    setTimeout(() => {
        el.classList.add('hide');
    }, 0);
}

function drop(ev) {
    ev.preventDefault();
    const id = ev.dataTransfer.getData("Text");
    const draggable = document.getElementById(id);
    const target = ev.target;

    // 定义正确的放置区域:仅#bracelet下的容器允许放置
    const isValidZone = target.closest('#bracelet') !== null;

    if (isValidZone) {
        // 放置到正确位置,显示元素
        target.appendChild(draggable);
        draggable.classList.remove('hide');
    } else {
        // 错误位置,先显示元素,等待dragEnd归位
        draggable.classList.remove('hide');
    }
}

function dragEnd(ev) {
    const draggable = ev.target;
    // 未成功放置(dropEffect为none)时,恢复到初始位置
    if (ev.dataTransfer.dropEffect === "none") {
        const originalParentId = draggable.getAttribute("data-parent");
        const originalParent = document.getElementById(originalParentId);
        originalParent.appendChild(draggable);
        draggable.classList.remove('hide');
    }
}

3. HTML注意事项

  • 原代码中#bracelet下的三个div使用了重复的id="div1",已修正为唯一ID(div1-1、div1-2、div1-3),符合HTML规范。

内容的提问来源于stack exchange,提问作者alfredo49

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:01:12