<p>Leaflet 1.7.1 provoque l'émission de 2 événements de clic par Leaflet Controls dans Safari</p>

Créé le 5 sept. 2020  ·  39Commentaires  ·  Source: Leaflet/Leaflet

Étapes à suivre pour reproduire
Étapes pour reproduire le comportement:

  • configurer une carte de base, avec un contrôle qui contient un bouton, qui écoute les événements de clic et publie les événements sur la console
  • cliquez sur le bouton dans le contrôle en utilisant Safari sur un Mac
  • voir deux événements de clic dans la console, un avec isTrusted:true et un autre avec des attributs isTrusted:false

(L'utilisation de `` forcer le toucher '' pour cliquer sur le bouton d'un trackpad entraîne l'émission d'un seul événement de clic, mais cela déclenche également la fenêtre contextuelle d'aperçu Safari.)

Comportement prévisible

Il ne doit y avoir qu'un seul événement de clic émis, avec l'attribut isTrusted:true .

Leaflet pourrait-il filtrer en toute sécurité les événements de clic avec isTrusted:false ?

Comportement actuel

Dans la version 1.6, le comportement attendu est observé. Dans la version 1.7.1, Chrome présente le comportement attendu, mais pas Safari.

Les différences entre les deux événements sont présentées ci-dessous.

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 et peut-être webkitForce semblent être les principales différences, mais il semble également étrange qu'il y ait différents horodatages et dimensions Y entre les deux événements.

Environnement

  • Version du dépliant: 1.7.1
  • Navigateur (avec version): Safari 13.1.2
  • OS / Plateforme (avec version): OS X 10.13.6 et 10.15.6

Contexte supplémentaire

J'ai remarqué cela après la mise à jour d'OpenStreetMap vers la dernière version de Leaflet, où le problème se manifeste en empêchant certains des outils de carte d'être utilisés car le premier événement active un outil et le second le désactive. Problème lié publié sur https://github.com/openstreetmap/openstreetmap-website/issues/2811

Exemple minimal reproduisant le problème

Veuillez consulter https://codepen.io/dankarran/pen/JjXMXzd

bug compatibility

Commentaire le plus utile

J'ai également rencontré ce problème dans Firefox (et Mobile Safari). Je n'ai pas été en mesure de le reproduire de manière fiable, mais l'allusion qu'il provient de l'option tap m'a conduit à la solution qui désactive complètement le tap car je n'en ai apparemment pas besoin pour ouvrir le popup, même en safari mobile:

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

Tous les 39 commentaires

Exemple minimal reproduisant le problème

Par souci de clarté: cet exemple utilise

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

Leaflet pourrait-il filtrer en toute sécurité les événements de clic avec isTrusted:false ?

Il serait possible de le faire, en addOne() en DomEvent.js , autour de https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/dom/DomEvent.js#L109

Avec une nouvelle branche dans cette chaîne if-then-else, quelque chose comme probablement

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

Cependant, je ne possède aucun matériel Apple (pour le moment), je ne peux donc pas tester cela; et je ne sais pas si cela pourrait avoir un impact sur les versions précédentes de Safari de bureau.

L'événement simulé provient de https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L100

Je suggère donc de changer la condition sur https://github.com/Leaflet/Leaflet/blob/4f32a5e83525a3a42980c974e48712b058510eb5/src/map/handler/Map.Tap.js#L87

dans quelque chose comme

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

Cependant, je ne possède aucun matériel Apple (pour le moment), je ne peux donc pas tester cela; et je ne sais pas si cela pourrait avoir un impact sur les versions précédentes de Safari de bureau ou sur d'autres navigateurs (le bogue peut-il se reproduire sur Firefox mobile?).

Je pense que ce bug a été introduit à

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

@ johnd0e , pouvez-vous jeter un œil? Peut-être avez-vous introduit ce changement pour tenir compte d'iOS mais avez involontairement affecté macOS de bureau?

Merci d'avoir regardé @IvanSanchez. Je suis heureux de vous aider à tester les modifications proposées sur Safari sur Mac ou iOS.

Juste pour ajouter, il y a un problème lié dans Safari sur iOS, mais il semble se comporter légèrement différemment. Je n'ai pas fait beaucoup de tests là-dessus.

@ johnd0e , pouvez-vous jeter un œil? Peut-être avez-vous introduit ce changement pour tenir compte d'iOS mais avez involontairement affecté macOS de bureau?

Cela visait définitivement à résoudre les problèmes iOS, voir la discussion: https://github.com/Leaflet/Leaflet/pull/7010.
Et nous utilisons la propriété safari intentionnellement, afin de ne pas être trop spécifique.

Corrections rapides possibles:

  • introduire Browser.ios propriété
  • ou utilisez Browser.safari && Browser.mobile

Mais que se passe-t-il si demain nous obtenons un macbook avec touchscren? Cela va tout casser à nouveau.

Je propose donc d'appliquer quickfix ( Browser.safari && Browser.mobile ) dès que possible, puis de discuter de la solution ultime ici: # 6980

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

J'aime cette approche (en tant que solution «rapide et sale»).

Mais que se passe-t-il si demain nous obtenons un macbook avec touchscren? Cela va tout casser à nouveau.

Vous savez que ma réponse, à la fin, sera # 7200 :-)

Vous savez que ma réponse, à la fin, sera # 7200 :-)

Je ne suis pas si sur)
Mais de toute façon, je préférerais corriger tout ce que nous pouvons en restant dans l'approche actuelle, puis aller plus loin (au # 7200 ou autre).

Je ne sais pas s'il s'agit du même problème (veuillez donc pardonner le marquage à la fin du ticket existant), mais Maj-glisser pour zoomer est également interrompu dans 1.7.1 sur Safari de bureau. Heureux d'ouvrir un nouveau problème si # 7260 ne l'a pas également résolu.

@systemed Pouvez-vous s'il vous plaît essayer le glissement de décalage en utilisant https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js ? (par exemple https://plnkr.co/edit/v4GzrCYSxpIO1aOo) C'est une construction de master qui inclut déjà les modifications de # 7260.

Spot on - cela fonctionne bien. 👍

Comme il est apparu, le même problème affecte non seulement Safari de bureau, mais également l'ancien Edge (et qui sait quoi d'autre).
Le gestionnaire AFAIK atm tap est nécessaire pour iOS uniquement .

Alors ... Peut-être devrions-nous changer map.options.tap default en false .

J'ai mis à jour mon codepen pour utiliser le code construit à partir de master, et également pour afficher les événements afin de faciliter le test sur mobile.

Cela fonctionne bien sur Safari de bureau, mais malheureusement, il semble que Safari mobile déclenche toujours deux événements de clic.

Si le JS à https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js est la dernière version, il déclenche toujours deux événements de clic sur iOS Safari.

@dagjomar
Êtes-vous en mesure d'inspecter ces événements?

Ce peut être un problème différent.

Parce que sur touchstart (et pointerdown ) nous empêchons click ici:
https://github.com/Leaflet/Leaflet/blob/dda26ba96d7dc79213818d1bcc0565b6ac3c69c4/src/map/handler/Map.Tap.js#L43
Et je ne vois aucune raison pour laquelle cela pourrait ne pas fonctionner.

@ johnd0e Je vais voir si je peux obtenir plus de détails et vous le faire savoir. Le type d'élément utilisé ferait-il une différence (par exemple a ou button qui auraient leurs propres gestionnaires de clics vs div qui ne le feraient pas)?

J'ai mis à jour le codepen pour enregistrer des détails d'événement simplifiés sur la console. Les événements sur iOS semblent être les mêmes que ceux vus sur le bureau avant cette mise à jour:

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

De plus, les éléments a et div se comportent de la même manière, et l'ajout de e.preventDefault() dans mon gestionnaire d'événements ne le résout pas.

Faites-moi savoir s'il y a autre chose que vous aimeriez que j'essaye @ johnd0e?

Est-il possible que les lignes suivantes ne soient pas nécessaires, si Safari déclenche ses propres événements de clic?

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

Au fait, je viens de vérifier et Chrome (v85) sur iOS se comporte de la même manière, avec deux événements déclenchés.

Ok, voyez ce que j'ai trouvé:
1) Empêcher mousedown / pointerdown n'annule pas click . Seuls touchstart peuvent être évités.
2) Mais actuellement Leaflet a un comportement plutôt étrange (# 7077): lorsque des événements de pointeur sont disponibles - il remplace les événements tactiles par des événements de pointeur.

C'est pourquoi nous avons maintenant ces clics supplémentaires.

Donc, pour résoudre ce problème correctement, nous devons adopter l'un de ceux-ci: # 7029, # 7026.
@IvanSanchez

Si cela aide comme solution rapide comme palliatif (et ne brise pas d'autres choses), commenter cet événement simulé semble fonctionner pour moi à la fois dans Chrome et Safari sur iOS ...

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

@systemed Pouvez-vous s'il vous plaît essayer le glissement de décalage en utilisant https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js ? (par exemple https://plnkr.co/edit/v4GzrCYSxpIO1aOo) C'est une construction de master qui inclut déjà les modifications de # 7260.

https://s3.amazonaws.com/leafletjs-cdn/content/leaflet/master/leaflet-src.js
^ cette version semble bien mieux fonctionner que 1.7.1 dans le bureau Safari 14.0.
appuyez ou cliquez sur les incendies une seule fois 👍

Si cela aide comme solution rapide comme palliatif (et ne brise pas d'autres choses), commenter cet événement simulé semble fonctionner pour moi à la fois dans Chrome et Safari sur iOS ...

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

J'ai eu le problème d'événement de 2 clics sur tous les appareils (Firefox de bureau, Chrome, Safari iOS, Chrome ..) et cela a résolu le problème

Le même problème m'arrive et n'arrive que dans Safari. Chrome et Firefox ne déclenchent l'événement qu'une seule fois MacOS 10.15.6 et Safari 14.0.

J'ai temporairement rétrogradé Leaflet à 1.6 et tout fonctionne normalement.

Y a-t-il une chance que ce bogue soit corrigé?
Quelqu'un y travaille-t-il?

Comme je l'ai déjà dit: le bogue est causé par un gestionnaire tap extrêmement obsolète (# 6980).

Pour faire démarrer les choses, nous devons prendre des décisions: https://github.com/Leaflet/Leaflet/issues/7255#issuecomment -691109158
@IvanSanchez @mourner

Pour faire démarrer les choses, nous devons prendre des décisions: # 7255 (commentaire)

@ johnd0e Je n'ai ni le temps de tester cela, ni aucun matériel iOS. Quoi qu'il en soit, je vous fais confiance à ce sujet, alors je donne le feu vert au # 7026 (qui semble plus propre que le # 7029)

Quelqu'un y travaille-t-il?

Vous savez ce qui serait cool, @ PeterPan73? Pour que vous puissiez continuer avec quelques builds à partir de # 7026 et # 7029, et de les tester pour d'autres problèmes de compatibilité, au lieu de simplement mettre plus de pression sur les mainteneurs.

donc je donne le feu vert au # 7026 (qui semble plus propre que le # 7029)

Malheureusement, dans le dernier commit de # 7026, j'ai dû appliquer de vilaines solutions de contournement afin de surmonter d' autres bogues (qui à leur tour peuvent être résolus par # 7029 et # 7059).

Donc à la fin, nous devrons encore faire face au # 7029 et aux autres PR connectés, c'est pourquoi je les ai tous réunis sous https://github.com/Leaflet/Leaflet/projects/1

Je rencontre ce problème sur macOS 10.15.7 à l'aide de Chrome 85 DevTools avec un appareil iOS activé. La solution de contournement la plus rapide pour moi a été d'utiliser la fonction lodash debounce .

Aujourd'hui, j'ai rencontré un problème, qui semble lié à celui-ci, je publierai donc mon expérience ici.
Cela se produit avec le trackpad Macbook et je l'ai découvert en essayant d'ajouter un menu contextuel personnalisé à la carte.
Ce qui se passe, c'est que, une fois que la carte a le focus, même si vous faites un clic droit pour le menu contextuel, Leaflet déclenchera un événement _click_ simulé, qui ne devrait pas être déclenché et a button valeur 0. Cela conduit à des interactions étranges avec mon gestionnaire proche pour le menu contextuel.

Pour produire le bogue, vous pouvez aller sur https://leafletjs.com puis:

  1. Cliquez sur la carte (pour que la carte soit focalisée)
  2. "Clic-droit"
  3. Cliquez sur la carte
  4. "Clic-droit"

Ce que vous verrez, c'est que le curseur est en mode glisser et une fois que vous cliquez deux fois sur la carte (une fois le menu contextuel fermé et une fois pour déclencher l'événement de clic), la carte sautera.

Peut-être que cela est également lié à d'autres problèmes (par exemple # 6865).

Cet événement de double clic (un de confiance, un non) se produit pour moi sur 1.7.1 lors de la simulation d'un mobile sur Chrome et Firefox sur un ordinateur de bureau Linux (ne s'est pas produit sur 1.6). Fonctionne bien sur de vrais appareils tactiles Android (testé Chrome / Firefox). Je l'ai pour l'instant résolu en implémentant ma propre minuterie de rebond dans le gestionnaire d'événements de clic, en filtrant les clics qui se produisent dans les 150 ms du dernier.

Je l'ai pour l'instant résolu en implémentant ma propre minuterie de rebond dans le gestionnaire d'événements de clic, en filtrant les clics qui se produisent dans les 150 ms du dernier.

Salut @atorger , comment avez-vous mis en œuvre cela? J'ai essayé event.originalEvent.preventDefault(); dans le gestionnaire d'événements onClick, mais sans succès. Pouvez-vous partager un exemple minimal? 🙏 😄

Je l'ai pour l'instant résolu en implémentant ma propre minuterie de rebond dans le gestionnaire d'événements de clic, en filtrant les clics qui se produisent dans les 150 ms du dernier.

Salut @atorger , comment avez-vous mis en œuvre cela? J'ai essayé event.originalEvent.preventDefault(); dans le gestionnaire d'événements onClick, mais sans succès. Pouvez-vous partager un exemple minimal? prie sourire

sûr:

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
    }
});

Notez que ce problème empêche également bindPopup de fonctionner avec les marqueurs:

J'ai également rencontré ce problème dans Firefox (et Mobile Safari). Je n'ai pas été en mesure de le reproduire de manière fiable, mais l'allusion qu'il provient de l'option tap m'a conduit à la solution qui désactive complètement le tap car je n'en ai apparemment pas besoin pour ouvrir le popup, même en safari mobile:

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

J'ai également rencontré ce problème dans Firefox (et Mobile Safari). Je n'ai pas été en mesure de le reproduire de manière fiable, mais l'allusion qu'il provient de l'option tap m'a conduit à la solution qui désactive complètement le tap car je n'en ai apparemment pas besoin pour ouvrir le popup, même en safari mobile:

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

Merci pour cette solution, @eikes! J'ai rencontré ce problème aujourd'hui et cela l'a résolu.

Je n'en ai apparemment pas besoin pour ouvrir le popup, même en safari mobile:

En safari mobile, le gestionnaire tap est nécessaire pour simuler l'événement contextmenu sur taphold.

Ce bogue déclenche deux touches lorsque vous essayez de cliquer sur une carte sur un appareil mobile.

Cette page vous a été utile?
0 / 5 - 0 notes