为何设置draggable="true"会阻止滚动?如何拖动时允许滚动?
问题原因
当元素设置draggable="true"后,浏览器的原生拖拽机制会优先捕获鼠标事件,容器的滚动事件会被抑制——拖拽过程中,浏览器专注处理拖拽相关逻辑,不会响应容器的滚动操作,因此拖动元素时无法滚动容器。
解决方法
可以通过监听拖拽相关事件,手动实现容器的滚动逻辑,以下是两种常见的实现方式:
方式1:拖拽时鼠标靠近容器边缘自动滚动
通过监听dragover事件,判断鼠标在容器内的位置,当靠近上下边缘时触发容器滚动:
.container{ height: 300px; overflow: scroll; background: green; position: relative; /* 确保鼠标位置计算准确 */ } .draggable{ background:red; padding: 10px; cursor: grab; }
<div class="container"> <p class="draggable" draggable="true">draggable</p> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> <div>qwerty</div> </div>
const container = document.querySelector('.container'); const draggable = document.querySelector('.draggable'); let scrollInterval; draggable.addEventListener('dragstart', () => { scrollInterval = null; }); container.addEventListener('dragover', (e) => { e.preventDefault(); const containerRect = container.getBoundingClientRect(); const mouseY = e.clientY; const edgeThreshold = 50; // 边缘触发滚动的距离 const scrollSpeed = 5; // 滚动速度 if (scrollInterval) clearInterval(scrollInterval); // 鼠标靠近顶部,向上滚动 if (mouseY < containerRect.top + edgeThreshold) { scrollInterval = setInterval(() => { container.scrollTop -= scrollSpeed; }, 16); } // 鼠标靠近底部,向下滚动 else if (mouseY > containerRect.bottom - edgeThreshold) { scrollInterval = setInterval(() => { container.scrollTop += scrollSpeed; }, 16); } }); draggable.addEventListener('dragend', () => { if (scrollInterval) clearInterval(scrollInterval); });
方式2:拖拽时允许鼠标滚轮滚动容器
如果希望拖拽元素时,通过鼠标滚轮也能滚动容器,可以监听wheel事件手动调整滚动位置:
const container = document.querySelector('.container'); const draggable = document.querySelector('.draggable'); let isDragging = false; draggable.addEventListener('dragstart', () => { isDragging = true; }); draggable.addEventListener('dragend', () => { isDragging = false; }); container.addEventListener('wheel', (e) => { if (isDragging) { e.preventDefault(); container.scrollTop += e.deltaY; } });
内容的提问来源于stack exchange,提问作者alexanne
相关产品推荐
相关产品推荐

