JUCE WKWebView中setPointerCapture导致pointerup/mouseup无法触发(macOS)
WKWebView滚动容器内卡片拖拽重排的释放事件丢失问题
我正在为JUCE插件的WebBrowserComponent(macOS下基于WKWebView)中的水平卡片布局实现拖拽重排交互。拖拽过程中卡片移动正常,但释放事件(pointerup、mouseup)始终无法触发。
正常工作的场景
- 旋钮拖拽:
canvas.setPointerCapture(id)+canvas.addEventListener('pointermove', ...)+canvas.addEventListener('pointerup', ...)→ 完全可用 - 滑块拖拽:在
<div>上使用相同模式 → 完全可用
无法正常工作的场景
- 节点卡片水平拖拽:在
overflow-x: auto的滚动容器内的卡片<div>上使用相同模式 →pointermove触发(卡片平移),但pointerup和mouseup在元素或document上都从未触发
实现代码
function attachDragReorder(card, getNodeIdx) { const handle = card.querySelector('.drag-handle'); let dragging = false, fromIdx = -1, lastDropIdx = -1, capturedId = null, startX = 0; const finish = (commit) => { if (!dragging) return; dragging = false; document.removeEventListener('pointerup', onDocUp, { capture: true }); document.removeEventListener('pointercancel', onDocCancel, { capture: true }); document.removeEventListener('mouseup', onDocMouseUp); try { card.releasePointerCapture(capturedId); } catch (_) {} // ... commit drop if commit=true }; const onDocUp = (e) => { if (e.pointerId === capturedId) finish(true); }; const onDocCancel = (e) => { if (e.pointerId === capturedId) finish(false); }; const onDocMouseUp = () => finish(true); handle.addEventListener('pointerdown', (e) => { if (e.button !== 0) return; capturedId = e.pointerId; card.setPointerCapture(capturedId); startX = e.clientX; dragging = true; card.classList.add('dragging'); document.addEventListener('pointerup', onDocUp, { capture: true }); document.addEventListener('pointercancel', onDocCancel, { capture: true }); document.addEventListener('mouseup', onDocMouseUp); }); card.addEventListener('pointermove', (e) => { if (!dragging) return; card.style.transform = `translateX(${e.clientX - startX}px)`; // ... update drop indicator }); card.addEventListener('pointerup', () => finish(true)); card.addEventListener('pointercancel', () => finish(false)); }
CSS样式
.node { touch-action: none; } .drag-handle { touch-action: none; cursor: grab; }
观察结果
- 移除
pointerdown中的e.preventDefault()无法解决问题 - 将
setPointerCapture从手柄<span>移到卡片<div>上,修复了pointermove触发问题,但pointerup仍无法触发 - 为卡片添加
touch-action: none无法修复pointerup问题 - 带有
{ capture: true }的文档级pointerup/mouseup监听器也无法触发 - 拖拽操作在
overflow-x: auto的滚动容器内——怀疑这会导致pointercancel提前触发并消耗事件
假设
当被指针捕获的元素应用transform: translateX()且指针离开元素原始可视边界时,WKWebView会触发pointercancel,导致dragging在mouseup触发前被重置为false。
问题
在WKWebView滚动容器内实现拖拽重排有没有已知可行的模式?我是否应该完全放弃指针事件,改用document上的mousedown/mousemove/mouseup?
环境:macOS、JUCE 8.x WebBrowserComponent(WKWebView)、Safari WebKit 18.x
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

