jQuery UI Droppable非嵌套重叠元素下阻止背景元素触发drop事件
问题说明
使用jQuery UI的droppable/draggable插件时,若页面存在两个非嵌套、因CSS布局导致位置重叠的放置区元素,拖拽元素释放后,上下层的两个放置区都会触发drop回调。
已尝试配置greedy: true参数,但该参数仅为DOM嵌套场景设计,作用是阻止drop事件向嵌套的父级放置区冒泡,对平级重叠元素不生效。
复现代码
HTML
<div id="contenitore"> <div id="carrello"> <p>Drop here</p> </div> <div id="carrello2"> <p>Drop here</p> </div> <div id="fagioli"> <p>Drag me</p> </div> </div>
JS
$(function() { $( "#fagioli" ).draggable(); $( "#carrello" ).droppable({ greedy: true, drop: function( event, ui ) { $( this ) .find( "p" ) .html( "Dropped." ); } }); $( "#carrello2" ).droppable({ greedy: true, drop: function( event, ui ) { $( this ) .find( "p" ) .html( "Dropped." ); } }); });
CSS
#contenitore {position: relative; width: 500px; height: 500px;} #carrello {background: #ccc;width:400px;height:500px;} #carrello2 {background: #ddd; width:300px;height:250px; position: absolute; bottom: 0px;} #fagioli {background: #822222;width:70px;height:90px;position: absolute; top: 200px; right: 10px;} #fagioli:hover {cursor:move}
解决方案
核心逻辑:仅允许鼠标释放位置视觉最顶层的放置区响应drop事件,被遮挡的下层放置区直接终止回调逻辑。
- 修改
draggable配置,让拖拽过程中的元素不拦截鼠标事件,避免干扰顶层元素判定:
$( "#fagioli" ).draggable({ start: function(e, ui) { // 拖拽元素设置为不响应鼠标事件,保证能正确识别下方的放置区层级 ui.helper.css("pointer-events", "none"); } });
- 给所有
droppable的drop回调增加顶层判定,非顶层元素直接跳过逻辑:
// 抽离通用drop处理逻辑 function handleDrop(event, ui) { // 获取鼠标释放坐标下最顶层的DOM元素 const topElement = document.elementFromPoint(event.clientX, event.clientY); // 当前放置区不是最顶层元素、也不包含最顶层元素时,说明被其他元素遮挡,直接返回 if (this !== topElement && !this.contains(topElement)) { return; } // 原有放置后的业务逻辑 $(this).find("p").html("Dropped."); } // 初始化droppable时复用处理逻辑 $( "#carrello" ).droppable({ greedy: true, drop: handleDrop }); $( "#carrello2" ).droppable({ greedy: true, drop: handleDrop });
该方案不需要手动维护元素z-index,可自动适配任意平级重叠的放置区场景,兼容所有现代浏览器及IE9+。
内容的提问来源于stack exchange,提问作者Tobia
相关产品推荐
相关产品推荐

