我有一个工作示例,其中包含
dragenter
和 dragleave
事件,突出显示应放置文件的区域。此示例工作正常。
现在,如果我只是在我的 Dragenter 区域内添加一个
<span>
,突出显示将不再正常工作(当您将图像悬停在文本顶部时 - 突出显示消失)。如您所见,dragleave
被调用了多次。
我所做的一切更改都是将
Drop files here
替换为 <span>Drop files here</span>
那里也有淘汰码,但我相信它与该错误无关。我知道问题出在事件冒泡上,但是
e.stopPropagation();
e.preventDefault();
return false;
没有帮助。知道如何让它与内部 dom 元素一起工作吗?
P.S.这只是一个简化的例子,看起来我无法正确制作它(我认为通过JS解决它的唯一方法,看来我描述的方式是可以解决的也可以使用 css)。很抱歉造成这种混乱。示例看起来更像是this。不仅文本位于可放置元素的内部,而且当您放置某些内容时,元素也会出现在那里。这些元素是可点击的。
Malk 解决方案的问题在于
:after
元素停留在这些可点击元素的顶部,从而使它们不可点击。
看起来您可以将处理程序附加到位于跨度之后和之上的覆盖 div:
<div class="col-md-12" data-bind="foreach: dropZones">
<div class="drop_zone">
<span>Drop files here</span>
<div class="drop_zone_overlay" data-bind="event:{
dragover: function(data, e){ $root.dragover(e);},
drop: function(data, e){ $root.drop(e, $data);},
dragenter: function(data, e){ $root.dragenter(e, $index());},
dragleave: function(data, e){ $root.dragleave(e, $index());}
}">
</div>
</div>
<ul data-bind="foreach: elements" style="height: 100px">
<li data-bind="text: $data"></li>
</ul>
</div>
CSS
.drop_zone {
border: 2px dashed #bbb;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
padding: 25px;
text-align: center;
font: 20pt bold'Vollkorn';
color: #bbb;
position:relative;
}
.drop_zone_overlay {
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
}
编辑
实际上你根本不需要添加其他元素。您可以使用 CSS
:after
创建一个伪元素,它应该能够覆盖内容。
.drop_zone {
...
position:relative;
}
.drop_zone:after{
content:'';
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
}
编辑2
您可以使用此技术仅在拖动时覆盖内容。您只需将
.css({})
调用更改为 toggleClass()
并将 :after
放在新类上即可。
这还可以让您创建一个为背景元素着色的叠加层:
.drop_zone_hover:after{
...
background-color:#0f0;
opacity:0.6;
}
我遇到了这个问题。而且,与大多数问题一样,它们可以用 javascript 解决。
像OP一样,我也不想让一个元素覆盖整个拖放区并使可点击的元素呈现惰性。
本质上,只需确保鼠标位置位于容器的边界框内即可。
在
dragleave
事件处理程序中,使用 currentTarget
获取 getBoundingClientRect
的边界框。
拖动事件将具有代表鼠标位置的
clientX
和 clientY
属性。
检查鼠标位置是否位于放置区的
top
、right
、bottom
和 left
边缘内。如果它在边界框内,则尽早返回并且不再处理 dragleave
事件。
const handleDragLeave = e => {
if (isInsideContainer(e)) return
e.currentTarget.classList.remove("dragged-over")
}
const isInsideContainer = e => {
const { top, bottom, left, right } = e.currentTarget.getBoundingClientRect()
return e.clientX < right && e.clientX > left && e.clientY > top && e.clientY < bottom
}
const dropzone = document.querySelector(".dropzone")
dropzone.addEventListener("dragenter", e => {
e.currentTarget.classList.add("dragged-over")
})
dropzone.addEventListener("dragleave", handleDragLeave)
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
display: grid;
place-items: center;
}
.dropzone {
border: 2px dashed black;
padding: 3rem;
display: grid;
place-items: center;
}
.dragged-over {
border-color: limegreen;
background-color: lightgrey;
}
span {
border: 1px solid blue;
}
<div class="dropzone">
<span>Drag and drop here</span>
</div>