html5可拖动隐藏原始元素



当开始使用HTML5可拖动属性拖动元素时,原始元素仍然可见,所以我最终看到了两个元素,而不是一个。

我该怎么做才能只让被拖动的元素可见(原始元素应该暂时隐藏)。

<script>
  function startDrag() {
    // hide initial element
  }
  function endDrag() {
    // reset initial element
  }
</script>
<div class="draggable" draggable="true"
  ondragstart="startDrag(event)"
  ondragend="endDrag(event)"
></div>

这里有一个jsfiddle来展示这个问题https://jsfiddle.net/gjc5p4qp/

您可以通过一个简单的解决方案成功实现这一点。原生的draggability不允许像opacity:0;visibility:hiddendisplay:none这样的CSS样式。

但您可以使用:transform:translateX(-9999px)

function startDrag(e) {
  let element = e.target;
  
  element.classList.add('hide');
}
function endDrag(e) {
  let element = e.srcElement;
  
  element.classList.remove('hide');
}
.draggable {
  border-radius: 4px;
  background: #CC0000;
  width: 40px;
  height: 40px;
}
.hide {
  transition: 0.01s;
  transform: translateX(-9999px);
}
<div
  class="draggable"
  draggable="true"
  ondragstart="startDrag(event)"
  ondragend="endDrag(event)"
/>

我已经用解决方案更新了您的JSFiddle。

[EDIT]:

用Andrew Hedges的建议更新了JSFiddle示例,使用requestAnimationFrame代替setTimeout

[编辑2]:

Jason Yin更新了一个更好的解决方案,添加了transition CSS属性,而不是使用requestAnimationFrame,它将处理从脚本转移到了渲染。

由于简单地设置visibility: hidden不起作用,我发现了另一个有点棘手的解决方案:在拖动事件开始一毫秒后设置visibility: hidden

function startDrag(e) {
  setTimeout(function() {
    e.target.style.visibility = "hidden";
  }, 1);
}
function endDrag(e) {
  setTimeout(function() {
    e.target.style.visibility = "";
  }, 1);
}
body {
  display: inline-block;
  outline: 1px solid black;
}
.draggable {
  border-radius: 4px;
  background: #CC0000;
  width: 40px;
  height: 40px;
}
<div class="draggable" draggable="true" ondragstart="startDrag(event)" ondragend="endDrag(event)">
</div>

这可以在没有之前答案中的技巧的情况下实现。

关键是要监听drag事件,而不是dragstart

//listen to drag event, not dragstart!
document.querySelector(".draggable").addEventListener("drag", (e)=>{
  e.target.classList.add("dragging");
});
document.querySelector(".draggable").addEventListener("dragend", (e)=>{
  e.target.classList.remove("dragging");
});
.draggable {
  width: 200px;
  height: 30px;
  background-color:#5856d6;
  text-align:center;
  line-height:30px;
}
.dragging {
  background: transparent;
  color: transparent;
  border: 1px solid #5856d6;
}
<div draggable="true" class="draggable">Drag me!</div>

如何隐藏元素

如果要隐藏元素,可以使用CSS属性visibility:hiddendisplay:none

我建议使用visibility属性,因为它可以在不更改文档布局的情况下隐藏元素。但是,如果你是元素的子元素,并且你想把它们隐藏起来,你需要在每个子元素上设置visibility:inherit

何时隐藏

您使用dragstart事件是正确的。但是,由draggable属性创建的元素的克隆会出现在dragstart事件的末尾。

因为JavaScript引擎是一个单线程解释器,如果你选择将其隐藏在这里,你的元素将被屏蔽为它的克隆,它将复制属性visibility:hidden。事实上,为了避免这种情况,您需要在Javascript调用堆栈中创建克隆后将其隐藏起来。

要执行此操作,请使用setTimout()函数并将其设置为0毫秒。这样,原始元素的掩码将在创建其克隆之后放置在堆栈的末尾。

在拖动结束时,要使其重新出现,只需要通过在dragend事件中调用visibility:visible将元素设置为可见。

代码示例

例如,代码可以如下所示:

<div 
    class="draggable" 
    draggable="true" 
    ondragstart="startDrag(event)" 
    ondragend="endDrag(event)" 
    style="background: #e66465; color:white; width:80px; height:20px; text-align:center;">
    Drag me
</div>
<script>
    function startDrag(e) {
        setTimeout(function(){
            e.target.style.visibility = "hidden";
        }, 0);
    }
    function endDrag(e){
        e.target.style.visibility = "visible";
    }
</script>

Filipe的回答真的很有帮助。如果setTimeoutrequestAnimationFrame不适合您。尝试添加过渡。

transition: transform 0.01s;
transform: translateX(-9999px);

您可以在dragStart事件中添加以下代码:

event.dataTransfer.setDragImage(new Image(), 0, 0); // Hide the dragged element

它将隐藏您的目标拖动元素。

发现:https://stackoverflow.com/a/35120001/1807542

使用一个干净的解决方案,将源/原始元素隐藏在dragov处理程序中。

var dragging;
function dragstart(e) {
  dragging = $(this);
}
function dragover(e) {
  dragging.hide();
}
function dragend(e) {
  if (dragging) {
    dragging.show();
    dragging = undefined;
  }
}

最新更新