Gestion de l'interaction SVG avec la propriété Pointer Events

Publié: 2022-03-10
Résumé rapide ↬ Voyons comment façonner l'interactivité des images SVG - c'est-à-dire contrôler quelles parties du document peuvent recevoir des clics, des touchers ou des tapotements - en utilisant la propriété pointer-events .

Essayez de cliquer ou de toucher l'image SVG ci-dessous. Si vous placez votre pointeur au bon endroit (le chemin ombré), la page d'accueil de Smashing Magazine devrait s'ouvrir dans un nouvel onglet du navigateur. Si vous avez essayé de cliquer sur un espace blanc, vous pourriez être vraiment confus à la place.

Voir le Pen Amethyst de Tiffany Brown (@webinista) sur CodePen.

Voir le Pen Amethyst de Tiffany Brown (@webinista) sur CodePen.

C'est le dilemme auquel j'ai été confronté lors d'un projet récent qui incluait des liens dans des images SVG. Parfois, lorsque je cliquais sur l'image, le lien fonctionnait. D'autres fois, ce n'était pas le cas. Confus, non?

Je me suis tourné vers la spécification SVG pour en savoir plus sur ce qui pourrait se passer et si SVG propose une solution. La réponse : pointer-events .

Plus après saut! Continuez à lire ci-dessous ↓

À ne pas confondre avec les événements de pointeur DOM ( D ocument O bject Model), pointer-events est à la fois une propriété CSS et un attribut d'élément SVG. Avec lui, nous pouvons gérer quelles parties d'un document ou d'un élément SVG peuvent recevoir des événements d'un dispositif de pointage tel qu'une souris, un trackpad ou un doigt.

Remarque sur la terminologie : "événements de pointeur" est également le nom d'une fonctionnalité de plate-forme Web indépendante de l'appareil pour la saisie de l'utilisateur. Cependant, dans cet article - et pour les besoins de la propriété pointer-events - l'expression "événements de pointeur" inclut également les événements de souris et tactiles.

Sortir des sentiers battus : le « modèle de forme » de SVG

L'utilisation de CSS avec HTML impose un modèle de mise en page de boîte sur HTML. Dans le modèle de disposition de boîte, chaque élément génère un rectangle autour de son contenu. Ce rectangle peut être en ligne, au niveau de la ligne, au niveau de la ligne atomique ou en bloc, mais il s'agit toujours d'un rectangle avec quatre angles droits et quatre arêtes. Lorsque nous ajoutons un lien ou un écouteur d'événement à un élément, la zone interactive correspond aux dimensions du rectangle.

Remarque : L'ajout d'un clip-path à un élément interactif modifie ses limites interactives. En d'autres termes, si vous ajoutez un clip-path de détourage hexagonal à a élément, seuls les points à l'intérieur du chemin de détourage seront cliquables. De même, l'ajout d'une transformation oblique transformera les rectangles en rhomboïdes.

SVG n'a pas de modèle de disposition de boîte. Vous voyez, lorsqu'un document SVG est contenu dans un document HTML, dans une mise en page CSS, l'élément SVG racine adhère au modèle de mise en page de la boîte. Ses éléments enfants ne le font pas. Par conséquent, la plupart des propriétés CSS liées à la mise en page ne s'appliquent pas au SVG.

Donc, à la place, SVG a ce que j'appellerai un "modèle de forme". Lorsque nous ajoutons un lien ou un écouteur d'événement à un document ou à un élément SVG, la zone interactive ne sera pas nécessairement un rectangle. Les éléments SVG ont une boîte englobante. La boîte englobante est définie comme : le rectangle le plus serré aligné avec les axes du système de coordonnées utilisateur de cet élément qui l'entoure entièrement ainsi que ses descendants. Mais initialement, les parties d'un document SVG qui sont interactives dépendent des parties qui sont visibles et/ou peintes .

Éléments peints vs éléments visibles

Les éléments SVG peuvent être "remplis" mais ils peuvent aussi être "traités". Le remplissage fait référence à l'intérieur d'une forme. Le trait fait référence à son contour.

Ensemble, "remplir" et "trait" sont des opérations de peinture qui restituent des éléments à l'écran ou à la page (également appelée canevas ). Lorsque nous parlons d' éléments peints , nous entendons que l'élément a un remplissage et/ou un trait. Habituellement, cela signifie que l'élément est également visible.

Cependant, un élément SVG peut être peint sans être visible. Cela peut se produire si la valeur de l'attribut visible ou la propriété CSS est hidden ou lorsque display est none . L'élément est là et occupe l'espace théorique. Nous ne pouvons tout simplement pas le voir (et la technologie d'assistance peut ne pas le détecter).

Peut-être plus déroutant, un élément peut également être visible - c'est-à-dire avoir une valeur de visibility calculée de visible - sans être peint. Cela se produit lorsque les éléments manquent à la fois d'un trait et d'un remplissage.

Remarque : Les valeurs de couleur avec transparence alpha (par exemple rgba(0,0,0,0) ) n'affectent pas si un élément est peint ou visible. En d'autres termes, si un élément a un remplissage ou un contour alpha transparent, il est peint même s'il n'est pas visible.

Savoir quand un élément est peint, visible ou ni l'un ni l'autre est crucial pour comprendre l'impact de chaque valeur pointer-events .

Tout ou rien ou quelque chose entre les deux : les valeurs

pointer-events est à la fois une propriété CSS et un attribut d'élément SVG. Sa valeur initiale est auto , ce qui signifie que seules les parties peintes et visibles recevront des événements de pointeur. La plupart des autres valeurs peuvent être divisées en deux groupes :

  1. Valeurs qui nécessitent qu'un élément soit visible ; et
  2. Des valeurs qui ne le sont pas.

painted , fill , stroke , et all entrent dans cette dernière catégorie. Leurs homologues dépendant de la visibilité — visiblePainted , visibleFill , visibleStroke et visible — tombent dans le premier.

La spécification SVG 2.0 définit également une valeur bounding-box . Lorsque la valeur de pointer-events est bounding-box , la zone rectangulaire autour de l'élément peut également recevoir des événements de pointeur. Au moment d'écrire ces lignes, seul Chrome 65+ prend en charge la valeur du bounding-box .

none est également une valeur valide. Il empêche l'élément et ses enfants de recevoir des événements de pointeur. La propriété CSS pointer-events peut également être utilisée avec des éléments HTML. Mais lorsqu'il est utilisé avec HTML, seuls auto et none sont des valeurs valides.

Étant donné que les valeurs pointer-events sont mieux démontrées qu'expliquées, regardons quelques démos.

Ici, nous avons un cercle avec un remplissage et un trait appliqués. C'est à la fois peint et visible . Le cercle entier peut recevoir des événements de pointeur, mais pas la zone à l'extérieur du cercle.

Voir le Pen Visible vs peint en SVG par Tiffany Brown (@webinista) sur CodePen.

Voir le Pen Visible vs peint en SVG par Tiffany Brown (@webinista) sur CodePen.

Désactivez le remplissage, de sorte que sa valeur soit none . Maintenant, si vous essayez de survoler, de cliquer ou d'appuyer sur l'intérieur du cercle, rien ne se passe. Mais si vous faites la même chose pour la zone de trait, les événements de pointeur sont toujours distribués. Changer la valeur de fill à none signifie que cette zone est visible , mais pas peinte .

Apportons une petite modification à notre balisage. Nous allons ajouter pointer-events="visible" à notre élément circle , tout en gardant fill=none .

Voir le Pen Comment ajouter des événements de pointeur : tout affecte l'interactivité par Tiffany Brown (@webinista) sur CodePen.

Voir le Pen Comment ajouter des événements de pointeur : tout affecte l'interactivité par Tiffany Brown (@webinista) sur CodePen.

Désormais, la zone non peinte encerclée par le trait peut recevoir des événements de pointeur.

Augmenter la zone cliquable d'une image SVG

Revenons à l'image du début de cet article. Notre "améthyste" est un élément de path , par opposition à un groupe de polygones chacun avec un stroke et un fill . Cela signifie que nous ne pouvons pas simplement ajouter pointer-events="all" et l'appeler un jour.

Au lieu de cela, nous devons augmenter la zone de clic. Utilisons ce que nous savons des éléments peints et visibles. Dans l'exemple ci-dessous, j'ai ajouté un rectangle à notre balisage d'image.

Voir le Pen Augmenter la zone de clic d'une image SVG par Tiffany Brown (@webinista) sur CodePen.

Voir le Pen Augmenter la zone de clic d'une image SVG par Tiffany Brown (@webinista) sur CodePen.

Même si ce rectangle n'est pas visible, il est toujours techniquement visible (c'est-à-dire visibility: visible ). Son absence de remplissage signifie cependant qu'il n'est pas peint . Notre image est la même. En effet, cela fonctionne toujours de la même manière - cliquer sur un espace blanc ne déclenche toujours pas d'opération de navigation. Nous devons encore ajouter un attribut pointer-events à notre élément a . L'utilisation des valeurs visible ou all fonctionnera ici.

Voir le Pen Augmenter la zone de clic d'une image SVG par Tiffany Brown (@webinista) sur CodePen.

Voir le Pen Augmenter la zone de clic d'une image SVG par Tiffany Brown (@webinista) sur CodePen.

Désormais, l'image entière peut recevoir des événements de pointeur.

L'utilisation bounding-box éliminerait le besoin d'un élément fantôme. Tous les points à l'intérieur de la boîte englobante recevraient des événements de pointeur, y compris l'espace blanc délimité par le chemin. Mais encore une fois : pointer-events="bounding-box" n'est pas largement pris en charge. En attendant, nous pouvons utiliser des éléments non peints.

Utilisation pointer-events lors du mélange de SVG et de HTML

Un autre cas où pointer-events peuvent être utiles : l'utilisation de SVG à l'intérieur d'un bouton HTML.

Voir le stylo Ovxmmy de Tiffany Brown (@webinista) sur CodePen.

Voir le stylo Ovxmmy de Tiffany Brown (@webinista) sur CodePen.

Dans la plupart des navigateurs - Firefox et Internet Explorer 11 sont des exceptions ici - la valeur de event.target sera un élément SVG au lieu de notre bouton HTML. Ajoutons pointer-events="none" à notre balise SVG d'ouverture.

Voir Pen How pointer-events: none can be used with SVG and HTML par Tiffany Brown (@webinista) sur CodePen.

Voir Pen How pointer-events: none can be used with SVG and HTML par Tiffany Brown (@webinista) sur CodePen.

Désormais, lorsque les utilisateurs cliqueront ou appuieront sur notre bouton, event.target fera référence à notre button .

Ceux qui connaissent bien le DOM et JavaScript noteront que l'utilisation du mot-clé function au lieu d'une fonction fléchée et this au lieu de event.target résout ce problème. Cependant, l'utilisation pointer-events="none" (ou pointer-events: none; dans votre CSS) signifie que vous n'avez pas à valider cette bizarrerie JavaScript particulière en mémoire.

Conclusion

SVG prend en charge le même type d'interactivité auquel nous sommes habitués avec HTML. Nous pouvons l'utiliser pour créer des graphiques qui répondent aux clics ou aux tapotements. Nous pouvons créer des zones liées qui ne respectent pas le modèle de boîte CSS et HTML. Et avec l'ajout de pointer-events , nous pouvons améliorer la façon dont nos documents SVG se comportent en réponse à l'interaction de l'utilisateur.

La prise en charge par le navigateur pointer-events SVG est robuste. Chaque navigateur prenant en charge SVG prend en charge la propriété pour les documents et éléments SVG. Lorsqu'il est utilisé avec des éléments HTML, le support est légèrement moins robuste. Il n'est pas disponible dans Internet Explorer 10 ou ses prédécesseurs, ni dans aucune version d'Opera Mini.

Nous venons d'effleurer la surface des pointer-events dans cet article. Pour un traitement technique plus approfondi, lisez la spécification SVG. MDN (Mozilla Developer Network) Web Docs propose une documentation plus conviviale pour les développeurs Web pour pointer-events , avec des exemples.