Gestionarea interacțiunii SVG cu proprietatea Pointer Events

Publicat: 2022-03-10
Rezumat rapid ↬ Să aruncăm o privire la cum să modelăm interactivitatea imaginilor SVG – adică să controlăm ce părți ale documentului pot primi clicuri, atingeri sau atingeri – folosind proprietatea pointer-events .

Încercați să dați clic sau să atingeți imaginea SVG de mai jos. Dacă puneți indicatorul în locul potrivit (calea umbrită), atunci ar trebui să aveți pagina de pornire a Smashing Magazine deschisă într-o nouă filă de browser. Dacă ați încercat să faceți clic pe un spațiu alb, este posibil să fiți foarte confuz.

Vedeți Pen Amethyst de Tiffany Brown (@webinista) pe CodePen.

Vedeți Pen Amethyst de Tiffany Brown (@webinista) pe CodePen.

Aceasta este dilema cu care m-am confruntat în timpul unui proiect recent care includea link-uri în imaginile SVG. Uneori, când făceam clic pe imagine, linkul funcționa. Alteori nu a făcut-o. Confuz, nu?

Am apelat la specificația SVG pentru a afla mai multe despre ce s-ar putea întâmpla și dacă SVG oferă o soluție. Răspunsul: pointer-events .

Mai multe după săritură! Continuați să citiți mai jos ↓

A nu se confunda cu evenimentele pointer DOM (Document O bject Model), pointer-events este atât o proprietate CSS, cât și un atribut de element SVG. Cu acesta, putem gestiona ce părți ale unui document sau element SVG pot primi evenimente de la un dispozitiv de indicare, cum ar fi un mouse, un trackpad sau un deget.

O notă despre terminologie: „evenimentele pointer” este, de asemenea, numele unei caracteristici de platformă web, independentă de dispozitiv, pentru introducerea utilizatorului. Cu toate acestea, în acest articol — și în sensul proprietății pointer-events — expresia „evenimente pointer” include și evenimente de mouse și touch.

În afara cutiei: „Modelul de formă” al SVG

Utilizarea CSS cu HTML impune un model de aspect al casetei pe HTML. În modelul de aspect al casetei, fiecare element generează un dreptunghi în jurul conținutului său. Acest dreptunghi poate fi inline, inline-level, atomic inline-level sau bloc, dar este tot un dreptunghi cu patru unghiuri drepte și patru margini. Când adăugăm un link sau un ascultător de evenimente la un element, zona interactivă se potrivește cu dimensiunile dreptunghiului.

Notă : Adăugarea unui clip-path la un element interactiv modifică limitele sale interactive. Cu alte cuvinte, dacă adăugați o clip-path decuplare hexagonală la a element, numai punctele din cadrul traseului de tăiere vor putea fi clicate. În mod similar, adăugarea unei transformări oblice va transforma dreptunghiuri în romboizi.

SVG nu are un model de aspect al casetei. Vedeți, atunci când un document SVG este conținut de un document HTML, într-un aspect CSS, elementul SVG rădăcină aderă la modelul de aspect al casetei. Elementele sale copil nu. Ca urmare, majoritatea proprietăților legate de aspectul CSS nu se aplică SVG.

Deci, în schimb, SVG are ceea ce voi numi un „model de formă”. Când adăugăm un link sau un ascultător de evenimente la un document sau element SVG, zona interactivă nu va fi neapărat un dreptunghi. Elementele SVG au o casetă de delimitare. Caseta de delimitare este definită ca: dreptunghiul cel mai strâns aliniat cu axele sistemului de coordonate utilizator al acelui element care îl înglobează în întregime pe acesta și descendenții săi. Dar, inițial, care părți ale unui document SVG sunt interactive depinde de părțile care sunt vizibile și/sau pictate .

Elemente pictate vs. vizibile

Elementele SVG pot fi „umplute”, dar pot fi și „mângâiate”. Umplerea se referă la interiorul unei forme. Accident vascular cerebral se referă la conturul său.

Împreună, „umplerea” și „trase” sunt operațiuni de pictură care redau elemente pe ecran sau pe pagină (cunoscute și sub numele de pânză ). Când vorbim despre elemente pictate , ne referim la faptul că elementul are umplere și/sau contur. De obicei, aceasta înseamnă că elementul este și el vizibil.

Cu toate acestea, un element SVG poate fi vopsit fără a fi vizibil. Acest lucru se poate întâmpla dacă valoarea atributului visible sau proprietatea CSS este hidden sau când display nu este none . Elementul este acolo și ocupă spațiu teoretic. Pur și simplu nu îl putem vedea (și este posibil ca tehnologia de asistență să nu o detecteze).

Poate mai confuz, un element poate fi, de asemenea, vizibil - adică are o valoare calculată a visibility de visible - fără a fi pictat. Acest lucru se întâmplă atunci când elementelor le lipsește atât un accident vascular cerebral, cât și o umplere.

Notă : Valorile de culoare cu transparență alfa (de ex rgba(0,0,0,0) ) nu afectează dacă un element este pictat sau vizibil. Cu alte cuvinte, dacă un element are umplere sau contur alfa transparent, este pictat chiar dacă nu poate fi văzut.

A ști când un element este pictat, vizibil sau niciunul este esențial pentru înțelegerea impactului fiecărei valori de pointer-events .

Toate sau niciunul sau ceva între ele: valorile

pointer-events este atât o proprietate CSS, cât și un atribut de element SVG. Valoarea sa inițială este auto , ceea ce înseamnă că numai porțiunile pictate și vizibile vor primi evenimente pointer. Majoritatea celorlalte valori pot fi împărțite în două grupuri:

  1. Valori care necesită ca un element să fie vizibil; și
  2. Valori care nu.

painted , fill , stroke și all se încadrează în această din urmă categorie. Omoloagele lor dependente de vizibilitate — visiblePainted , visibleFill , visibleStroke și visible — se încadrează în primele.

Specificația SVG 2.0 definește, de asemenea, o valoare a bounding-box . Când valoarea pointer-events este bounding-box , zona dreptunghiulară din jurul elementului poate primi și evenimente pointer. În momentul scrierii acestui articol, numai Chrome 65+ acceptă valoarea bounding-box .

none este, de asemenea, o valoare validă. Împiedică elementul și copiii săi să primească orice eveniment pointer. Proprietatea CSS pointer-events poate fi folosită și cu elemente HTML. Dar atunci când este folosit cu HTML, numai auto și none sunt valori valide.

Deoarece valorile pointer-events sunt mai bine demonstrate decât explicate, să ne uităm la câteva demonstrații.

Aici avem un cerc cu o umplere și un accident vascular cerebral aplicat. Este și pictat și vizibil . Întregul cerc poate primi evenimente pointer, dar zona din afara cercului nu poate.

Vedeți Pen Visible vs pictat în SVG de Tiffany Brown (@webinista) pe CodePen.

Vedeți Pen Visible vs pictat în SVG de Tiffany Brown (@webinista) pe CodePen.

Dezactivați umplerea, astfel încât valoarea acesteia să nu fie none . Acum, dacă încercați să treceți cu mouse-ul, să faceți clic sau să atingeți interiorul cercului, nu se întâmplă nimic. Dar dacă procedați la fel pentru zona stroke, evenimentele pointer sunt încă trimise. Schimbarea valorii de fill la none înseamnă că această zonă este vizibilă , dar nu este pictată .

Să facem o mică modificare a marcajului nostru. Vom adăuga pointer-events="visible" elementului nostru circle , păstrând în același timp fill=none .

Vedeți Pen How adăugarea de evenimente pointer: toate afectează interactivitatea de Tiffany Brown (@webinista) pe CodePen.

Vedeți Pen How adăugarea de evenimente pointer: toate afectează interactivitatea de Tiffany Brown (@webinista) pe CodePen.

Acum, zona nevopsită înconjurată de accident vascular cerebral poate primi evenimente pointer.

Mărirea zonei pe care se poate face clic a unei imagini SVG

Să revenim la imaginea de la începutul acestui articol. „Ametistul” nostru este un element de path , spre deosebire de un grup de poligoane fiecare cu o stroke și o fill . Asta înseamnă că nu putem doar să adăugăm pointer-events="all" și să numim asta.

În schimb, trebuie să mărim zona de clic. Să folosim ceea ce știm despre elementele pictate și vizibile. În exemplul de mai jos, am adăugat un dreptunghi la marcajul imaginii noastre.

Vedeți Creionul Creșterea zonei de clic a unei imagini SVG de Tiffany Brown (@webinista) pe CodePen.

Vedeți Creionul Creșterea zonei de clic a unei imagini SVG de Tiffany Brown (@webinista) pe CodePen.

Chiar dacă acest dreptunghi este nevăzut, este încă vizibil din punct de vedere tehnic (adică visibility: visible ). Lipsa sa de umplutură înseamnă însă că nu este vopsită . Imaginea noastră arată la fel. Într-adevăr, funcționează în continuare la fel - făcând clic pe spațiul alb tot nu declanșează o operațiune de navigare. Mai trebuie să adăugăm un atribut pointer-events la elementul nostru a . Utilizarea valorilor visible sau a all valorilor va funcționa aici.

Vedeți Creionul Creșterea zonei de clic a unei imagini SVG de Tiffany Brown (@webinista) pe CodePen.

Vedeți Creionul Creșterea zonei de clic a unei imagini SVG de Tiffany Brown (@webinista) pe CodePen.

Acum întreaga imagine poate primi evenimente pointer.

Utilizarea bounding-box ar elimina necesitatea unui element fantomă. Toate punctele din cadrul casetei de delimitare vor primi evenimente pointer, inclusiv spațiul alb închis de cale. Dar din nou: pointer-events="bounding-box" nu este acceptat pe scară largă. Până când este, putem folosi elemente nevopsite.

Utilizarea pointer-events atunci când amestecați SVG și HTML

Un alt caz în care pointer-events pot fi utile: utilizarea SVG în interiorul unui buton HTML.

Vedeți Pen Ovxmmy de Tiffany Brown (@webinista) pe CodePen.

Vedeți Pen Ovxmmy de Tiffany Brown (@webinista) pe CodePen.

În majoritatea browserelor – Firefox și Internet Explorer 11 sunt excepții aici – valoarea event.target va fi un element SVG în loc de butonul nostru HTML. Să adăugăm pointer-events="none" la eticheta noastră SVG de deschidere.

Vedeți Pen How pointer-evenimente: niciunul nu poate fi folosit cu SVG și HTML de Tiffany Brown (@webinista) pe CodePen.

Vedeți Pen How pointer-evenimente: niciunul nu poate fi folosit cu SVG și HTML de Tiffany Brown (@webinista) pe CodePen.

Acum, când utilizatorii dau clic sau ating butonul nostru, event.target se va referi la button nostru .

Cei cunoscători în DOM și JavaScript vor observa că utilizarea cuvântului cheie al function în loc de o funcție săgeată și this în loc de event.target rezolvă această problemă. Folosirea pointer-events="none" (sau pointer-events: none; în CSS-ul dvs.), înseamnă totuși că nu trebuie să trimiteți acea particularitate JavaScript în memorie.

Concluzie

SVG acceptă același tip de interactivitate cu care ne-am obișnuit cu HTML. Îl putem folosi pentru a crea diagrame care răspund la clicuri sau atingeri. Putem crea zone legate care nu aderă la modelul casetei CSS și HTML. Și prin adăugarea de pointer-events , putem îmbunătăți modul în care documentele noastre SVG se comportă ca răspuns la interacțiunea utilizatorului.

Suportul de browser pentru pointer-events SVG este robust. Fiecare browser care acceptă SVG acceptă proprietatea documentelor și elementelor SVG. Când este utilizat cu elemente HTML, suportul este puțin mai puțin robust. Nu este disponibil în Internet Explorer 10 sau predecesorii săi sau în nicio versiune de Opera Mini.

Tocmai am zgâriat suprafața pointer-events în această piesă. Pentru un tratament tehnic mai aprofundat, citiți specificația SVG. MDN (Mozilla Developer Network) Web Docs oferă mai multă documentație prietenoasă pentru dezvoltatori web pentru pointer-events , completată cu exemple.