当开始使用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:hidden
或display: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:hidden
或display: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的回答真的很有帮助。如果setTimeout
或requestAnimationFrame
不适合您。尝试添加过渡。
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;
}
}