You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 21:08:09