<p>Leaflet 1.7.1导致Safari中的Leaflet Controls发出2单击事件</p>

创建于 2020-09-05  ·  39评论  ·  资料来源: Leaflet/Leaflet

重现步骤
重现行为的步骤:

  • 设置基本地图,并在其中包含带有按钮的控件,该控件侦听单击事件并将事件发布到控制台
  • 在Mac上使用Safari单击控件中的按钮
  • 在控制台中看到两个单击事件,一个具有isTrusted:true isTrusted:false属性,另一个具有

(使用“强制触摸”单击触控板上的按钮只会导致发出一次单击事件,但也会触发Safari预览弹出窗口。)

预期行为

仅应发出一个带有isTrusted:true属性的click事件。

Leaflet是否可以使用isTrusted:false安全地过滤掉点击事件?

当前行为

在1.6版中,观察到了预期的行为。 在1.7.1版中,Chrome展示了预期的行为,但Safari没有。

这两个事件之间的差异包括在下面。

MouseEvent 1:

MouseEvent

_simulated: true
composed: false
isTrusted: false
layerX: 15
layerY: 28
offsetX: 15
offsetY: 28
pageX: 410
pageY: 46
screenX: 1390
screenY: 189
timeStamp: 499337
webkitForce: 0
x: 410
y: 38

MouseEvent 2:

MouseEvent

composed: true
isTrusted: true
layerX: 15
layerY: 20
offsetX: 15
offsetY: 20
pageX: 410
pageY: 38
screenX: 1390
screenY: 189
timeStamp: 538265
webkitForce: 1
x: 410
y: 38

_simulatedcomposedisTrusted以及也许webkitForce似乎是关键的区别,但是在两者之间存在不同的时间戳和Y维也很奇怪。两个事件。

环境

  • 传单版本:1.7.1
  • 浏览器(带有版本):Safari 13.1.2
  • 操作系统/平台(带有版本):OS X 10.13.6和10.15.6

其他背景

在OpenStreetMap更新到最新版本的Leaflet之后,我注意到了这一点,该问题通过阻止使用某些地图工具而显现出来,因为第一个事件将工具打开,第二个事件将其关闭。 相关问题发布在https://github.com/openstreetmap/openstreetmap-website/issues/2811

重现问题的最小示例

请参阅https://codepen.io/dankarran/pen/JjXMXzd

bug compatibility

最有用的评论

我也在Firefox(和移动Safari)中也遇到了这个问题。 我无法可靠地重现它,但是提示来自tap选项,这导致我找到了完全禁用tap的解决方案,因为我显然不需要它来打开弹出窗口,即使在移动safari上也是如此:

var map = L.map('map', { "tap": false });

所有39条评论

重现问题的最小示例

为了清楚起见:该示例使用

    L.DomEvent.on(container, "click", function(e) {

Leaflet是否可以使用isTrusted:false安全过滤掉点击事件?

可能会这样做,在https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/dom/DomEvent.js#L109中的addOne()DomEvent.js

在if-then-else链中有了一个新分支,大概是

} else if (Browser.safari && !Browser.mobile && type === 'click') {
  handler = function (ev) {
    if (ev.isTrusted) { originalHandler(ev); }
  }
  obj.addEventListener('click', handler, false);
} // etc

但是,我目前没有任何Apple硬件,因此无法测试。 而且我不知道这是否会影响以前版本的桌面Safari。

模拟事件来自https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L100

所以我建议在https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L87更改条件

变成像

if (this._fireClick && e && e.changedTouches && !(Browser.safari && !Browser.mobile)) { 

但是,我目前没有任何Apple硬件,因此无法测试。 而且我不知道这是否会影响台式机Safari或其他浏览器的早期版本(该错误是否可能在firefox mobile上重现?)。

我认为这个错误是在

https://github.com/Leaflet/Leaflet/pull/7010/files#diff -c2e3d5ef35bf1c4a7c6b549ddf734725R134

@ johnd0e ,你可以看看吗? 也许您是针对iOS引入了此更改,但无意中影响了桌面macOS?

感谢您关注@IvanSanchez。 我很乐意帮助您在Mac或iOS上的Safari中测试任何建议的更改。

补充一下,iOS上的Safari中存在一个相关问题,但它的行为似乎略有不同。 我没有做太多的测试。

@ johnd0e ,你可以看看吗? 也许您是针对iOS引入了此更改,但无意中影响了桌面macOS?

那绝对是为了解决iOS问题,请参见讨论: https :
并且我们故意使用safari属性,以免过于具体。

可能的快速修复:

  • 介绍Browser.ios属性
  • 或使用Browser.safari && Browser.mobile

但是,如果明天我们将获得带touchscren的Macbook呢? 那将再次破坏一切。

因此,我建议尽快应用quickfix( Browser.safari && Browser.mobile ),然后在此处讨论最终解决方案:#6980

* or use `Browser.safari && Browser.mobile`

我喜欢这种方法(作为“快速而肮脏的”修复程序)。

但是,如果明天我们将获得带touchscren的Macbook呢? 那将再次破坏一切。

您知道我的答案最终将是#7200 :-)

您知道我的答案最终将是#7200 :-)

我不太确定)
但是无论如何,我宁愿修复我们目前所能使用的所有方法,然后再进一步发展(到#7200或其他任何方法)。

不确定这是否是相同的问题(因此请原谅在现有票证的末尾加标签),但在桌面Safari上的1.7.1中也发生了shift-drag放大问题。 如果#7260也未解决此问题,我们很乐意打开一个新期刊。

@systemed您可以尝试使用https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js进行拖动吗? (例如https://plnkr.co/edit/v4GzrCYSxpIO1aOo)这是来自master的构建,其中已经包含对#7260的更改。

当场-正常工作。 👍

如图所示,同一问题不仅影响台式机Safari,而且还影响旧版Edge(谁知道其他什么)。
iOS需要AFAIK atm tap处理程序。

所以...可能是我们应该将map.options.tap default更改为false

我已经更新了Codepen以使用从master生成的代码,并且还显示事件以使其更易于在移动设备上进行测试。

它在桌面Safari上运行良好,但不幸的是,看起来移动Safari仍在触发两次单击事件。

如果位于https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js的JS是最新版本,则它仍会在iOS Safari上触发两次点击事件。

@dagjomar
您能够检查那些事件吗?

这可能是不同的问题。

因为在touchstart (和pointerdown )上,我们在这里防止click
https://github.com/Leaflet/Leaflet/blob/dda26ba96d7dc79213818d1bcc0565b6ac3c69c4/src/map/handler/Map.Tap.js#L43
而且我看不出任何原因可能不起作用。

@ johnd0e我看看是否可以得到更多详细信息,并告诉您。 使用哪种类型的元素(例如,具有自己的点击处理程序的abutton与没有元素的div会有所不同)吗?

我已经更新了代码笔,将一些简化的事件详细信息记录到那里的控制台中。 此更新之前,iOS上的事件似乎与桌面上的事件相同:

type: click
isTrusted: false
composed: false
_simulated: true
webkitForce: 0
type: click
isTrusted: true
composed: true
webkitForce: 1

此外, adiv元素的行为相同,并且在事件处理程序中添加e.preventDefault()不能解决问题。

让我知道您是否还想尝试@ johnd0e?

如果Safari触发自己的点击事件,是否有可能不需要以下几行?

https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L98 -L101

顺便说一句,我刚刚检查了一下,iOS上的Chrome(v85)的运行方式是否相同,并触发了两个事件。

好的,看看我发现了什么:
1)防止mousedown / pointerdown不会取消click 。 只能防止touchstart
2)但是,当前Leaflet的行为很怪异(#7077):当指针事件可用时-用触摸事件代替触摸事件。

这就是为什么我们现在有了这些额外的点击。

因此,要正确解决此问题,我们应采用以下一项:#7029,#7026。
@伊万·桑切斯

如果它可以作为一种快速解决办法(暂时解决)(并且不会破坏其他功能),请注释一下,模拟事件似乎确实适用于iOS上的Chrome和Safari ...

https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L100

@systemed您可以尝试使用https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js进行拖动吗? (例如https://plnkr.co/edit/v4GzrCYSxpIO1aOo)这是来自master的构建,其中已经包含对#7260的更改。

https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js
^在桌面Safari 14.0中,此版本的工作方式似乎比1.7.1更好。
点击或单击一次射击fire

如果它可以作为一种快速解决办法(暂时解决)(并且不会破坏其他功能),请注释一下,模拟事件似乎确实适用于iOS上的Chrome和Safari ...

https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L100

我在所有设备(台式机Firefox,chrome,ios safari,chrome ..)上遇到了2次点击事件问题,这解决了该问题

同样的问题发生在我身上,仅在Safari中发生。 Chrome和Firefox仅在MacOS 10.15.6和Safari 14.0触发事件。

我暂时将Leaflet降级为1.6,一切正常。

是否有可能修复此错误?
有人在工作吗?

正如我已经说过的:该错误是由过时的tap处理程序(#6980)引起的。

为了使事情起步,我们需要做出一些决定: https :
@伊万·桑切斯@哀悼者

为了使事情起步,我们需要做出一些决定: #7255(评论)

@ johnd0e我既没有时间测试它,也没有任何iOS硬件。 无论如何,我对此深信不疑,所以我正在批准#7026(比#7029干净)

有人在工作吗?

你知道什么很棒,@ PeterPan73? 为了使您继续从#7026和#7029进行几个构建,并测试它们的进一步兼容性问题,而不仅仅是给维护者施加更大的压力。

所以我正在绿灯#7026(感觉比#7029干净)

不幸的是,在上一次提交的#7026中,我不得不应用丑陋的变通办法来克服其他错误(而这些

因此,最后我们仍然必须处理#7029和其他连接的PR,这就是为什么我将它们全部合并在https://github.com/Leaflet/Leaflet/projects/1下的原因

我在启用了iOS设备的Chrome 85 DevTools上在macOS 10.15.7上遇到了此问题。 对我来说,最快的解决方法是使用lodash debounce函数。

今天,我遇到了一个问题,似乎与此问题有关,所以我将在这里发表自己的经验。
这是Macbook触控板发生的,我在尝试向地图添加自定义上下文菜单时发现了它。
发生的事情是,一旦地图获得焦点,即使您右键单击上下文菜单,Leaflet也会触发一个模拟的_click_事件,该事件不应被触发并且具有button值0。这导致与我对contextmenu的关闭处理程序。

要产生此错误,您可以转到https://leafletjs.com ,然后:

  1. 单击地图(因此地图具有焦点)
  2. “右键点击”
  3. 点击地图
  4. “右键点击”

您将看到的是光标处于拖动模式,并且一旦您两次单击地图(一次关闭contextmenu并触发一次click事件),地图就会跳转。

也许这也涉及其他一些问题(例如,#6865)。

当我在台式机Linux上的Chrome和Firefox上模拟移动设备时,在我的1.7.1上发生了两次单击事件(一个受信任,一个未被信任)(1.6上没有发生)。 不过,该工具在真实的Android触摸设备上效果很好(已通过Chrome / Firefox测试)。 现在,我已经通过在click事件处理程序中实现自己的退回计时器来解决此问题,并过滤掉自上一次点击起150毫秒内发生的点击。

现在,我已经通过在click事件处理程序中实现自己的退回计时器来解决此问题,并过滤掉自上一次点击起150毫秒内发生的点击。

@atorger ,您是如何实现的? 我在onClick事件处理程序中尝试了event.originalEvent.preventDefault(); ,但没有成功。 您能否分享一个简单的例子? 😄

现在,我已经通过在click事件处理程序中实现自己的退回计时器来解决此问题,并过滤掉自上一次点击起150毫秒内发生的点击。

@atorger ,您是如何实现的? 我在onClick事件处理程序中尝试了event.originalEvent.preventDefault(); ,但没有成功。 您能否分享一个简单的例子? 祈祷微笑

当然:

var lastClick = Date.now();
e.addEventListener('click', function(event) {
    var now = Date.now();
    var diff = now - lastClick;
    lastClick = now;
    event.stopPropagation();
    if (diff > 150) {
        // handle the click event
    }
});

请注意,此问题还会导致bindPopup无法与标记一起使用:

我也在Firefox(和移动Safari)中也遇到了这个问题。 我无法可靠地重现它,但是提示来自tap选项,这导致我找到了完全禁用tap的解决方案,因为我显然不需要它来打开弹出窗口,即使在移动safari上也是如此:

var map = L.map('map', { "tap": false });

我也在Firefox(和移动Safari)中也遇到了这个问题。 我无法可靠地重现它,但是提示来自tap选项,这导致我找到了完全禁用tap的解决方案,因为我显然不需要它来打开弹出窗口,即使在移动safari上也是如此:

var map = L.map('map', { "tap": false });

感谢您提供此解决方案,@ eikes! 我今天遇到了这个问题,并解决了这个问题。

我显然不需要它来打开弹出窗口,即使在移动safari上也是如此:

在移动浏览器中,需要tap处理程序来模拟Taphold上的contextmenu事件。

尝试在移动设备上单击地图时,此错误会触发两次触摸。

此页面是否有帮助?
0 / 5 - 0 等级