30

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

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

<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/

4

7 回答 7

25

您可以通过一个 hacky 解决方案来成功。本机可拖动性不允许 CSS 样式,如opacity:0;visibility:hiddendisplay:none.

但是您可以使用: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

[编辑]:

使用Andrew Hedges建议更新了 JSFiddle示例,改为使用.requestAnimationFramesetTimeout

[编辑 2]:

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

于 2016-04-02T23:07:27.197 回答
13

由于简单的设置visibility: hidden不起作用,我找到了另一个有点hacky的解决方案: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>

于 2016-04-03T13:21:30.993 回答
7

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

关键是监听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>

于 2020-07-08T08:24:54.970 回答
1

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

transition: transform 0.01s;
transform: translateX(-9999px);
于 2020-12-14T09:37:30.177 回答
0

如何隐藏你的元素

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

我推荐使用该visibility属性,因为它隐藏了一个元素而不改变文档的布局。但是,如果你的元素有子元素并且你想隐藏它们,你需要visibility:inherit在每个子元素上进行设置。

什么时候隐藏

你使用这个dragstart事件是对的。但是由可拖动属性创建的元素的克隆出现在dragstart事件的末尾。

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

为此,请使用该setTimout()功能并将其设置为 0 ms。这样,在创建他的克隆之后,原始元素的掩码被放在堆栈的末尾。

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

代码示例

例如,代码如下所示:

<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>

于 2021-11-07T04:36:48.877 回答
0

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

使用一个干净的解决方案来隐藏拖动处理程序中的源/原始元素。

var dragging;
function dragstart(e) {
  dragging = $(this);
}

function dragover(e) {
  dragging.hide();
}

function dragend(e) {
  if (dragging) {
    dragging.show();
    dragging = undefined;
  }
}
于 2019-08-15T00:26:13.657 回答
0

您可以将此代码添加到您的 dragStart 事件中:

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

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

于 2021-01-17T09:16:28.817 回答