Gestione dell'interazione SVG con la proprietà Pointer Events
Pubblicato: 2022-03-10pointer-events
.Prova a fare clic o toccare l'immagine SVG di seguito. Se metti il puntatore nel posto giusto (il percorso ombreggiato), dovresti avere la home page di Smashing Magazine aperta in una nuova scheda del browser. Se hai provato a fare clic su uno spazio bianco, potresti invece essere davvero confuso.
Questo è il dilemma che ho dovuto affrontare durante un recente progetto che includeva collegamenti all'interno di immagini SVG. A volte, quando ho fatto clic sull'immagine, il collegamento funzionava. Altre volte no. Confuso, giusto?
Mi sono rivolto alle specifiche SVG per saperne di più su cosa potrebbe accadere e se SVG offre una soluzione. La risposta: pointer-events
.
Da non confondere con gli eventi puntatore DOM (Document O bject M odel ) , pointer-events
è sia una proprietà CSS che un attributo di elemento SVG. Con esso, possiamo gestire quali parti di un documento o elemento SVG possono ricevere eventi da un dispositivo di puntamento come un mouse, un trackpad o un dito.
Una nota sulla terminologia: "eventi puntatore" è anche il nome di una funzionalità della piattaforma Web indipendente dal dispositivo per l'input dell'utente. Tuttavia, in questo articolo, e ai fini della proprietà pointer-events
, la frase "eventi puntatore" include anche eventi del mouse e del tocco.
Fuori dagli schemi: il "Modello di forma" di SVG
L'uso di CSS con HTML impone un modello di layout a scatola su HTML. Nel modello di layout box, ogni elemento genera un rettangolo attorno al suo contenuto. Quel rettangolo può essere inline, inline-level, atomic inline-level o block, ma è comunque un rettangolo con quattro angoli retti e quattro bordi. Quando aggiungiamo un link o un listener di eventi a un elemento, l'area interattiva corrisponde alle dimensioni del rettangolo.
Nota : l'aggiunta di un clip-path
a un elemento interattivo ne altera i limiti interattivi. In altre parole, se aggiungi un clip-path
di ritaglio esagonale a a
elemento, solo i punti all'interno del tracciato di ritaglio saranno selezionabili. Allo stesso modo, l'aggiunta di una trasformazione di inclinazione trasformerà i rettangoli in romboidi.
SVG non ha un modello di layout box. Vedete, quando un documento SVG è contenuto da un documento HTML, all'interno di un layout CSS, l'elemento SVG radice aderisce al modello di layout box. I suoi elementi figlio non lo fanno. Di conseguenza, la maggior parte delle proprietà relative al layout CSS non si applicano a SVG.
Quindi, invece, SVG ha quello che chiamerò un "modello di forma". Quando aggiungiamo un collegamento o un listener di eventi a un documento o elemento SVG, l'area interattiva non sarà necessariamente un rettangolo. Gli elementi SVG hanno un riquadro di delimitazione. Il riquadro di delimitazione è definito come: il rettangolo più stretto allineato con gli assi del sistema di coordinate utente di quell'elemento che lo racchiude interamente e i suoi discendenti.
Ma inizialmente, quali parti di un documento SVG sono interattive dipende da quali parti sono visibili e/o dipinte .
Elementi dipinti contro elementi visibili
Gli elementi SVG possono essere "riempiti" ma possono anche essere "accarezzati". Il riempimento si riferisce all'interno di una forma. Il tratto si riferisce al suo contorno.
Insieme, "riempimento" e "tratto" sono operazioni di pittura che eseguono il rendering di elementi sullo schermo o sulla pagina (nota anche come tela ). Quando si parla di elementi dipinti si intende che l'elemento ha un riempimento e/o un tratto. Di solito, questo significa che anche l'elemento è visibile.
Tuttavia, un elemento SVG può essere dipinto senza essere visibile. Ciò può verificarsi se il valore dell'attributo visible
o la proprietà CSS è hidden
o quando la display
è none
. L'elemento c'è e occupa uno spazio teorico. Non riusciamo a vederlo (e la tecnologia assistiva potrebbe non rilevarlo).
Forse in modo più confuso, un elemento può anche essere visibile, cioè avere un valore di visibility
calcolato di visible
, senza essere dipinto. Ciò accade quando gli elementi mancano sia di un tratto che di un riempimento.
Nota : i valori di colore con trasparenza alfa (ad es rgba(0,0,0,0)
) non influiscono sul fatto che un elemento sia dipinto o visibile. In altre parole, se un elemento ha un riempimento o un tratto alfa trasparente, viene dipinto anche se non può essere visto.
Sapere quando un elemento è dipinto, visibile o nessuno dei due è fondamentale per comprendere l'impatto di ciascun valore pointer-events
.
Tutto o nessuno o qualcosa nel mezzo: i valori
pointer-events
è sia una proprietà CSS che un attributo di elemento SVG. Il suo valore iniziale è auto
, il che significa che solo le parti dipinte e visibili riceveranno eventi puntatore. La maggior parte degli altri valori può essere divisa in due gruppi:
- Valori che richiedono che un elemento sia visibile; e
- Valori che non lo fanno.
painted
, fill
, stroke
e all
rientrano in quest'ultima categoria. Le loro controparti dipendenti dalla visibilità - visiblePainted
, visibleFill
, visibleStroke
e visible
- rientrano nel primo.
La specifica SVG 2.0 definisce anche un valore bounding-box
. Quando il valore di pointer-events
è bounding-box
, anche l'area rettangolare attorno all'elemento può ricevere eventi pointer. Al momento della stesura di questo articolo, solo Chrome 65+ supporta il valore bounding-box
.
none
è anche un valore valido. Impedisce all'elemento e ai suoi figli di ricevere qualsiasi evento del puntatore. La proprietà CSS pointer-events
può essere utilizzata anche con elementi HTML. Ma se utilizzato con HTML, solo auto
e none
sono valori validi.
Poiché i valori pointer-events
sono meglio dimostrati che spiegati, diamo un'occhiata ad alcune demo.
Qui abbiamo un cerchio con un riempimento e un tratto applicati. È sia dipinto che visibile . L'intero cerchio può ricevere eventi puntatore, ma l'area al di fuori del cerchio no.
Disabilita il riempimento, in modo che il suo valore sia none
. Ora, se provi a passare con il mouse, fare clic o toccare l'interno del cerchio, non succede nulla. Ma se fai lo stesso per l'area del tratto, gli eventi del puntatore vengono comunque inviati. Modificare il valore di fill
su none
significa che quest'area è visibile , ma non dipinta .
Facciamo una piccola modifica al nostro markup. Aggiungeremo pointer-events="visible"
al nostro elemento circle
, mantenendo fill=none
.
Ora l'area non dipinta circondata dal tratto può ricevere eventi puntatore.
Aumentare l'area selezionabile di un'immagine SVG
Torniamo all'immagine dall'inizio di questo articolo. La nostra "ametista" è un elemento di path
, al contrario di un gruppo di poligoni ciascuno con un stroke
e un fill
. Ciò significa che non possiamo semplicemente aggiungere pointer-events="all"
e chiamarlo un giorno.
Invece, dobbiamo aumentare l'area di clic. Usiamo ciò che sappiamo sugli elementi dipinti e visibili. Nell'esempio seguente, ho aggiunto un rettangolo al markup dell'immagine.
Anche se questo rettangolo non è visibile, è ancora tecnicamente visibile (es visibility: visible
). La mancanza di riempimento, tuttavia, significa che non è dipinto . La nostra immagine sembra la stessa. In effetti funziona ancora allo stesso modo: fare clic su uno spazio bianco non attiva ancora un'operazione di navigazione. Abbiamo ancora bisogno di aggiungere un attributo pointer-events
al nostro a
. L'uso del visible
o di all
valori funzionerà qui.
Ora l'intera immagine può ricevere eventi puntatore.
L'uso bounding-box
eliminerebbe la necessità di un elemento fantasma. Tutti i punti all'interno del riquadro di delimitazione riceverebbero eventi puntatore, incluso lo spazio bianco racchiuso dal percorso. Ma ancora: pointer-events="bounding-box"
non è ampiamente supportato. Fino a quando non lo è, possiamo usare elementi non verniciati.
Utilizzo pointer-events
durante la miscelazione di SVG e HTML
Un altro caso in cui pointer-events
possono essere utili: usare SVG all'interno di un pulsante HTML.
Nella maggior parte dei browser — Firefox e Internet Explorer 11 sono eccezioni qui — il valore di event.target
sarà un elemento SVG invece del nostro pulsante HTML. Aggiungiamo pointer-events="none"
al nostro tag SVG di apertura.
Ora, quando gli utenti fanno clic o toccano il nostro pulsante, event.target
farà riferimento al nostro button
.
Gli esperti di DOM e JavaScript noteranno che l'utilizzo della parola chiave function
invece di una funzione freccia e this
invece di event.target
risolve questo problema. L'uso pointer-events="none"
(o pointer-events: none;
nel tuo CSS), tuttavia, significa che non devi impegnare quella particolare stranezza JavaScript in memoria.
Conclusione
SVG supporta lo stesso tipo di interattività a cui siamo abituati con HTML. Possiamo usarlo per creare grafici che rispondono a clic o tocchi. Possiamo creare aree collegate che non aderiscono al modello box CSS e HTML. E con l'aggiunta di pointer-events
, possiamo migliorare il modo in cui i nostri documenti SVG si comportano in risposta all'interazione dell'utente.
Il supporto del browser per pointer-events
SVG è solido. Ogni browser che supporta SVG supporta la proprietà per i documenti e gli elementi SVG. Se utilizzato con elementi HTML, il supporto è leggermente meno robusto. Non è disponibile in Internet Explorer 10 o nei suoi predecessori, né in nessuna versione di Opera Mini.
Abbiamo appena graffiato la superficie degli pointer-events
in questo pezzo. Per un trattamento tecnico più approfondito, leggere le specifiche SVG. MDN (Mozilla Developer Network) Web Docs offre una documentazione più intuitiva per gli sviluppatori Web per pointer-events
, completa di esempi.