重现步骤
重现行为的步骤:
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
_simulated
, composed
, isTrusted
以及也许webkitForce
似乎是关键的区别,但是在两者之间存在不同的时间戳和Y维也很奇怪。两个事件。
环境
其他背景
在OpenStreetMap更新到最新版本的Leaflet之后,我注意到了这一点,该问题通过阻止使用某些地图工具而显现出来,因为第一个事件将工具打开,第二个事件将其关闭。 相关问题发布在https://github.com/openstreetmap/openstreetmap-website/issues/2811
重现问题的最小示例
重现问题的最小示例
为了清楚起见:该示例使用
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。
变成像
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我看看是否可以得到更多详细信息,并告诉您。 使用哪种类型的元素(例如,具有自己的点击处理程序的a
或button
与没有元素的div
会有所不同)吗?
我已经更新了代码笔,将一些简化的事件详细信息记录到那里的控制台中。 此更新之前,iOS上的事件似乎与桌面上的事件相同:
type: click
isTrusted: false
composed: false
_simulated: true
webkitForce: 0
type: click
isTrusted: true
composed: true
webkitForce: 1
此外, a
和div
元素的行为相同,并且在事件处理程序中添加e.preventDefault()
不能解决问题。
让我知道您是否还想尝试@ johnd0e?
如果Safari触发自己的点击事件,是否有可能不需要以下几行?
顺便说一句,我刚刚检查了一下,iOS上的Chrome(v85)的运行方式是否相同,并触发了两个事件。
好的,看看我发现了什么:
1)防止mousedown
/ pointerdown
不会取消click
。 只能防止touchstart
。
2)但是,当前Leaflet的行为很怪异(#7077):当指针事件可用时-用触摸事件代替触摸事件。
这就是为什么我们现在有了这些额外的点击。
因此,要正确解决此问题,我们应采用以下一项:#7029,#7026。
@伊万·桑切斯
如果它可以作为一种快速解决办法(暂时解决)(并且不会破坏其他功能),请注释一下,模拟事件似乎确实适用于iOS上的Chrome和Safari ...
@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 ...
我在所有设备(台式机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 ,然后:
您将看到的是光标处于拖动模式,并且一旦您两次单击地图(一次关闭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
事件。
尝试在移动设备上单击地图时,此错误会触发两次触摸。
最有用的评论
我也在Firefox(和移动Safari)中也遇到了这个问题。 我无法可靠地重现它,但是提示来自tap选项,这导致我找到了完全禁用tap的解决方案,因为我显然不需要它来打开弹出窗口,即使在移动safari上也是如此: