如何立即触发 dragend 事件

How to fire dragend event immediately

我正在尝试解决触发 dragend event immediately, when dragged outside the draggable area. For example, notice in the following video, there is about a 0.25s delay when dragging the tag outside the draggable area (when inside it, it registers immediately): https://gyazo.com/18d1afc32eb065d1f35896697ef0479e 的问题。

这是 JSFiddle:http://jsfiddle.net/radonirinamaminiaina/zfnj5rv4/

这个问题大约 7 年前在这里被问到:HTML5 dragend event firing immediately,但是当它被问到时这似乎更像是浏览器限制,我认为我的问题有很大不同。

有没有办法在拖动到可拖动区域之外时立即触发事件?比如在jfiddle的例子中,如果"This div is draggable"被拖到浏览器的左上角,对于它来说'snap back'零延迟?

更新 来自评论中的一个问题:这是我正在尝试做的一个示例,其中有一个来自 table 中的 Pivot table 的 4s 视频30=]:gyazo.com/3ccd1c3abd7f92d3410022a83b5c25b9。基本上,当用户拖动标签时 "outside of the drag zone" 我希望能够立即删除该标签或触发显示标签已被删除的动画。

您可以尝试在删除这样的元素时自己触发 dragend 事件:

document.addEventListener("drop", function( event ) {
    event.preventDefault();

    // currentTarget refers to document because I added the listener on it.
    event.currentTarget.dispatchEvent(new Event('dragend'));
}, false);

我无法测试这是否会删除动画,因为它似乎是由 MacOS 引起的行为?

另请注意,这可能会使事件 dragend 触发两次。

希望对您有所帮助!

您描述的内容与 Chrome 和 Firefox 中跨 Linux 和 Windows(桌面)系统的测试不一致。由于 COVID 情况,我无法轻松访问其他浏览器 + OS 组合(我不完全是 Apple 粉丝),但这是我制作的 fiddle,您可以在其中测试任何其他浏览器这样的组合:

https://jsfiddle.net/websiter/9d7cfbmx/embedded/result/#Result

它如何测试:它测量 dropdragend 事件之间的毫秒差异。它还将它们中的每一个存储到一个数组中,提供当前存储案例的 minmaxavg 值。如您所见,差异在 0.15ms1.75ms 之间变化,平均值为 ~0.5ms

因为它是一个实用的原型制作工具,所以我使用 Vue 来 update/display 统计数据,但这根本不会干扰正在测量的事件(您会注意到它们都发生并且是在 Vue 之外测量的并且数据更新发生在 setTimeout() 内,以确保我根本不会干扰测试)。

不幸的是,Firefox 将 performance.now() 值四舍五入为 1ms,因此它不会为您提供亚毫秒 minmax 值,但平均值似乎是一致的与 Chrome 中的那些(实际上在我的测试中略小)。

以上建议您的前提是 dragend 事件存在 250ms 延迟是不准确的,除非这两个事件都延迟了相同的时间。如果是这样,它 将是可见的 。四分之一秒是人眼可以察觉的。

我继续为 250ms 添加了一个可视化测试器到上面的 fiddle。


另请注意:看您的演示视频,您似乎使用的是 Apple 设备,但没有提供有关使用的浏览器的线索。如果非要我猜的话,我会说它是 Safari。

要禁用该动画必须满足两个条件:

  • 您必须在 dragover 事件中调用 preventDefault()(您已经这样做了)
  • drop 事件需要在 dragend 之前触发(根据 this answer

为了使第二个条件发生,如果事件的相关目标是 <html>,您可以在 dragleave 中调度 drop。我真的没有看到其他选择:

document.addEventListener("dragleave", function(event) {
  if (event.relatedTarget.tagName === 'HTML') {
    document.dispatchEvent(new Event('drop'));
  }
})

注意:通过在拖出 <html> 时调用 drop,您将打破任何将内容从浏览器拖出到任何其他程序(AFAIK,这是预期用途之一)的情况的研发)。此外,为了确保您只在实际拖出视口时才执行调度,您应该添加此 CSS 位:body { min-height: 100vh; }.

此外,如前所述,我现在无法在 Mac 上进行测试,因此我不保证此 hack 有效。它应该,但是......这是一个 Apple 实现,你知道吗?就说苹果吧,一切皆有可能。也许是因为它被咬了,谁知道呢? :)

您可以测试 hack here


如果上面没有隐藏动画,this might。查看 dragend 了解详情。 (这是尝试不预先触发 drop(不符合原则),而是从 dragend 触发它并重新发送可取消的 dragend 模拟)。恕我直言,值得一试。

这就是我的答案;不知道为什么,但它奏效了!

document.addEventListener("dragover", function( event ) {
    event.preventDefault();
}, false);