首页 > 解决方案 > 如何立即触发 dragend 事件

问题描述

dragend当拖动到可拖动区域之外时,我正在尝试解决立即触发事件的问题。例如,请注意以下视频中,将标签拖动到可拖动区域外时大约有 0.25 秒的延迟(当在可拖动区域内时,它会立即注册):https ://gyazo.com/18d1afc32eb065d1f35896697ef0479e 。

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

大约 7 年前在这里问过这个问题:HTML5 dragend event fire immediate,但这似乎更像是一个浏览器限制,我认为我的问题有点不同。

有没有办法在将事件拖到可拖动区域之外时立即触发事件?例如,在 jfiddle 示例中,如果“This div is draggable”被拖到浏览器的左上角,是否可以以零延迟“回弹”?

从评论中的问题更新:这是我正在尝试做的一个示例,其中包含来自 Excel 数据透视表的 4s 视频:gyazo.com/3ccd1c3abd7f92d3410022a83b5c25b9。基本上,当用户将标签拖到“拖动区域之外”时,我希望能够立即删除该标签或触发显示该标签已被删除的动画。

标签: javascriptbrowserdom-events

解决方案


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

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

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

因为它是一个实用的原型设计工具,所以我使用 Vue 来更新/显示统计数据,但这根本不应该干扰被测量的事件(你会注意到它们都发生并且在 Vue 之外进行测量,并且数据更新发生在setTimeout(),以确保我根本不会干扰测试)。

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

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

我继续为250ms上面的小提琴添加了一个视觉测试器。


另一个注意事项:查看您的演示视频,您似乎使用的是 Apple 设备,但它没有提供有关所使用浏览器的任何线索。如果我不得不猜测我会说它是 Safari。

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

  • 你必须调用preventDefault()事件dragover(你已经这样做了)
  • drop事件需要在时间被触发时被触发dragend(根据这个答案

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

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

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

另外,正如已经提到的,我现在无法在 Mac 上进行测试,所以我不保证这个 hack 有效。它应该,但是......这是苹果的实现,你知道吗?让我们说苹果一切皆有可能。也许是因为它被咬了,谁知道呢?:)

你可以在这里测试破解。


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


推荐阅读