有没有办法拖动和复制,但用 "draggable" 防止掉落? (JavaScript)

Is there a way to drag and copy, but prevent the drop with "draggable"? (JavaScript)

现在我有一个功能性的拖动和复制。我想知道是否有任何方法可以拖动副本,但不能放下。例如,如果用户按住 shift 键,he/she 可以快速单击并放下克隆,而不会放下被拖动的元素。如果通过文档上下搜索并没有找到任何东西。

这是我的代码 https://jsfiddle.net/jado66/f8b4ms36/2/ :

<!DOCTYPE html>
<html>
<head>
  <title>Drag Copy</title>
</head>
<style>

* {user-select: none; } 
.cell {width:50px;height:50px;
  }
img {width:50px;height:50px;cursor: move;}
table td #dropTable td:hover{background: #dedede;}
#dropTable {
    border-spacing: 5px;
    border: 1px solid #dedede;
}
.droppable:hover{
    transform: scale(1.05);
    transition-duration: 0.3s;
}

#dropTable tbody { height:300px; overflow-y:auto;  }

</style>

<body>
   

     <!-- Drag Table -->
    
        <table style="border-spacing: 5px;">
            <tr>
                <td id="image1">
                    <div class = "cell" ondrop="drop(event)" ondragover="allowDrop(event)">
                        <img class = "droppable newGate" src="droppable" src="https://picsum.photos/500/500?random=1"   
                      ondragstart="dragStart(event)" id="1" draggable="true"/> </div>
                </td>
                <td id="image2">
                    <div class = "cell " ondrop="drop(event)" ondragover="allowDrop(event)">
                        <img class = "droppable" src="https://picsum.photos/500/500?random=2"   
                      ondragstart="dragStart(event)" id="2" draggable="true" /> </div>
                </td>
    
            </tr>
        </table>
        <hr>
        <!-- Drop Table -->
        <table>
            <tr>
                <td>
                    <table id="dropTable" >
                    <tr >
                        <td> <div class = "cell"></div></td> 
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                    </tr>
                    <tr>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                    </tr>
                    </tr>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                        <td> <div class = "cell" ></div></td>
                    </tr>
                    </table>
                </td>
            </tr>
        </table>
    <script>
    
const cells = document.querySelectorAll(".cell:empty"); //We only want to add event listeners to empty cells
for (const cell of cells){
    cell.addEventListener('dragover',allowDrop);
    cell.addEventListener('drop',drop);
}

function dragStart(evt)
{
    evt.dataTransfer.setData("Text",evt.target.id);
}

function drop(evt)
{
    var data = evt.dataTransfer.getData("Text");
    var nodeCopy = document.getElementById(data).cloneNode(true);
    nodeCopy.id = Date.now(); /* We cannot use the same ID */
    evt.target.appendChild(nodeCopy);
    
    if (evt.shiftKey){
        console.log("Shift key pressed. Copy but keep drag");
      //Invoke drag command, or prevent drop, etc.
    }
}

function allowDrop(ob)
{
    ob.preventDefault();
}
    
    </script>
    </body>
    </html>

简而言之,没有

回答您的问题是否可以在用户释放鼠标按钮时阻止拖放事件:否。

来自the spec

Otherwise, if the user ended the drag-and-drop operation (e.g. by releasing the mouse button in a mouse-driven drag-and-drop interface), or if the drag event was canceled, then this will be the last iteration.

然而,当用户放下节点时,可能会立即触发一个新的 DragStart 事件,但我无法让它工作。在规范中找不到任何关于不可能的内容,但我可能是错的。

针对您的特定用例的解决方法

这只是一个概念验证 fiddle,代码看起来不太好,我敢肯定它有错误,但它可以满足您的要求:https://jsfiddle.net/y9Lpxdea/3/。按住您的 shift 键并在插槽上拖动以克隆当前 object 所持有的。

通过将要从 onDragStart 克隆的元素的 ID 存储在变量中(不在 DataTransfer object 中,因为 DataTransfer.getData() is only accessible on the drop event) 您可以在 onDragEnter 事件中访问当前持有的 object 的 ID,然后从那里复制 child。我保留了当前的拖放功能而没有保持 shift 键不变。

let dragId = null;

function dragStart(evt)
{
    evt.dataTransfer.setData("Text",evt.target.id);
    dragId = evt.target.id;
}

function dragEnter(evt)
{
    if (evt.shiftKey && dragId){
        var nodeCopy = document.getElementById(dragId).cloneNode(true);
        nodeCopy.id = Date.now(); /* We cannot use the same ID */
        evt.target.innerHTML = "";
        evt.target.appendChild(nodeCopy);
    }
}

function drop(evt)
{
    var data = evt.dataTransfer.getData("Text");
    var nodeCopy = document.getElementById(data).cloneNode(true);
    nodeCopy.id = Date.now(); /* We cannot use the same ID */
    evt.target.appendChild(nodeCopy);
    dragId = null;
}