html5 可拖动隐藏原始元素
html5 draggable hide original element
当开始使用 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/
您可以使用一个 hacky 解决方案来成功。本机可拖动性不允许 CSS 样式,例如:opacity:0;
、visibility:hidden
或 display: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。
[编辑]:
使用 requestAnimationFrame
代替 setTimeout
更新了 JSFiddle example with 建议。
[编辑 2]:
通过 添加 transition
CSS 属性 而不是使用 requestAnimationFrame
更新了更好的解决方案,它将处理从脚本编写转移到渲染。
由于简单地设置 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>
找到这个:
用一个干净的解决方案来隐藏 dragover 处理程序中的 source/original 元素。
var dragging;
function dragstart(e) {
dragging = $(this);
}
function dragover(e) {
dragging.hide();
}
function dragend(e) {
if (dragging) {
dragging.show();
dragging = undefined;
}
}
这可以在没有以前答案的 hack trick 的情况下实现。
重点是监听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>
Filipe 的回答真的很有帮助。如果 setTimeout
或 requestAnimationFrame
对您不起作用。尝试添加过渡。
transition: transform 0.01s;
transform: translateX(-9999px);
您可以将此代码添加到您的 dragStart 事件中:
event.dataTransfer.setDragImage(new Image(), 0, 0); // Hide the dragged element
它将隐藏您的目标拖动元素。
如何隐藏元素
如果你想隐藏你的元素,你可以使用 CSS 属性 visibility:hidden
or display:none
.
我推荐使用 visibility
属性 因为它隐藏了一个元素而不改变文档的布局。但是,如果您的元素有孩子并且想将它们隐藏到其中,则需要在每个孩子上设置 visibility:inherit
。
何时隐藏它
您使用 dragstart
事件是正确的。但是由 draggable 属性创建的元素的克隆出现在 dragstart
事件的末尾。
因为 JavaScript 引擎是一个 single-threaded 解释器,如果您选择在此处隐藏它,您的元素将被屏蔽为它的克隆,它将复制 属性 visibility:hidden
。事实上,为了避免这种情况,您需要在 Javascript callstack.
中创建克隆后将其隐藏
为此,请使用 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>
当开始使用 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/
您可以使用一个 hacky 解决方案来成功。本机可拖动性不允许 CSS 样式,例如:opacity:0;
、visibility:hidden
或 display: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。
[编辑]:
使用 requestAnimationFrame
代替 setTimeout
更新了 JSFiddle example with
[编辑 2]:
通过 transition
CSS 属性 而不是使用 requestAnimationFrame
更新了更好的解决方案,它将处理从脚本编写转移到渲染。
由于简单地设置 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>
找到这个:
用一个干净的解决方案来隐藏 dragover 处理程序中的 source/original 元素。
var dragging;
function dragstart(e) {
dragging = $(this);
}
function dragover(e) {
dragging.hide();
}
function dragend(e) {
if (dragging) {
dragging.show();
dragging = undefined;
}
}
这可以在没有以前答案的 hack trick 的情况下实现。
重点是监听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>
Filipe 的回答真的很有帮助。如果 setTimeout
或 requestAnimationFrame
对您不起作用。尝试添加过渡。
transition: transform 0.01s;
transform: translateX(-9999px);
您可以将此代码添加到您的 dragStart 事件中:
event.dataTransfer.setDragImage(new Image(), 0, 0); // Hide the dragged element
它将隐藏您的目标拖动元素。
如何隐藏元素
如果你想隐藏你的元素,你可以使用 CSS 属性 visibility:hidden
or display:none
.
我推荐使用 visibility
属性 因为它隐藏了一个元素而不改变文档的布局。但是,如果您的元素有孩子并且想将它们隐藏到其中,则需要在每个孩子上设置 visibility:inherit
。
何时隐藏它
您使用 dragstart
事件是正确的。但是由 draggable 属性创建的元素的克隆出现在 dragstart
事件的末尾。
因为 JavaScript 引擎是一个 single-threaded 解释器,如果您选择在此处隐藏它,您的元素将被屏蔽为它的克隆,它将复制 属性 visibility:hidden
。事实上,为了避免这种情况,您需要在 Javascript callstack.
为此,请使用 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>