Gerenciando a interação SVG com a propriedade Pointer Events

Publicados: 2022-03-10
Resumo rápido ↬ Vamos dar uma olhada em como moldar a interatividade das imagens SVG — ou seja, controlar quais partes do documento podem receber cliques, toques ou toques — usando a propriedade pointer-events .

Tente clicar ou tocar na imagem SVG abaixo. Se você colocar o ponteiro no lugar certo (o caminho sombreado), você deverá ter a página inicial da Smashing Magazine aberta em uma nova guia do navegador. Se você tentou clicar em algum espaço em branco, pode ficar realmente confuso.

Veja a Caneta Ametista de Tiffany Brown (@webinista) no CodePen.

Veja a Caneta Ametista de Tiffany Brown (@webinista) no CodePen.

Este é o dilema que enfrentei durante um projeto recente que incluiu links em imagens SVG. Às vezes, quando eu clicava na imagem, o link funcionava. Outras vezes não. Confuso, certo?

Voltei-me para a especificação SVG para saber mais sobre o que pode estar acontecendo e se o SVG oferece uma correção. A resposta: pointer-events .

Mais depois do salto! Continue lendo abaixo ↓

Não deve ser confundido com eventos de ponteiro DOM ( D ocument O bject M odel ), pointer-events é tanto uma propriedade CSS quanto um atributo de elemento SVG. Com ele, podemos gerenciar quais partes de um documento ou elemento SVG podem receber eventos de um dispositivo apontador, como mouse, trackpad ou dedo.

Uma observação sobre a terminologia: "eventos de ponteiro" também é o nome de um recurso de plataforma da Web independente de dispositivo para entrada do usuário. No entanto, neste artigo — e para fins da propriedade pointer-events — a frase "eventos de ponteiro" também inclui eventos de mouse e toque.

Fora da caixa: o “modelo de forma” do SVG

Usar CSS com HTML impõe um modelo de layout de caixa em HTML. No modelo de layout de caixa, cada elemento gera um retângulo em torno de seu conteúdo. Esse retângulo pode ser inline, inline-level, inline-level atômico ou bloco, mas ainda é um retângulo com quatro ângulos retos e quatro arestas. Quando adicionamos um link ou um ouvinte de evento a um elemento, a área interativa corresponde às dimensões do retângulo.

Nota : Adicionar um clip-path a um elemento interativo altera seus limites interativos. Em outras palavras, se você adicionar um clip-path hexagonal a a elemento a, somente os pontos dentro do caminho de recorte serão clicáveis. Da mesma forma, adicionar uma transformação de inclinação transformará retângulos em rombóides.

O SVG não possui um modelo de layout de caixa. Veja, quando um documento SVG está contido em um documento HTML, dentro de um layout CSS, o elemento SVG raiz adere ao modelo de layout de caixa. Seus elementos filho não. Como resultado, a maioria das propriedades relacionadas ao layout CSS não se aplica ao SVG.

Então, em vez disso, o SVG tem o que chamarei de 'modelo de forma'. Quando adicionamos um link ou um ouvinte de evento a um documento ou elemento SVG, a área interativa não será necessariamente um retângulo. Os elementos SVG têm uma caixa delimitadora. A caixa delimitadora é definida como: o retângulo de ajuste mais apertado alinhado com os eixos do sistema de coordenadas do usuário desse elemento que o envolve inteiramente e seus descendentes. Mas, inicialmente, quais partes de um documento SVG são interativas depende de quais partes são visíveis e/ou pintadas .

Elementos Pintados vs. Visíveis

Os elementos SVG podem ser “preenchidos”, mas também podem ser “acariciados”. Preenchimento refere-se ao interior de uma forma. Stroke refere-se ao seu contorno.

Juntos, “preencher” e “traçar” são operações de pintura que renderizam elementos para a tela ou página (também conhecida como tela ). Quando falamos de elementos pintados , queremos dizer que o elemento possui um preenchimento e/ou um traço. Normalmente, isso significa que o elemento também é visível.

No entanto, um elemento SVG pode ser pintado sem ser visível. Isso pode acontecer se o valor do atributo visible ou a propriedade CSS estiver hidden ou quando a display for none . O elemento está lá e ocupa o espaço teórico. Simplesmente não podemos vê-lo (e a tecnologia assistiva pode não detectá-lo).

Talvez mais confuso, um elemento também pode ser visível - ou seja, ter um valor de visibility calculado de visible - sem ser pintado. Isso acontece quando os elementos não possuem um traço e um preenchimento.

Nota : Os valores de cor com transparência alfa (por exemplo rgba(0,0,0,0) ) não afetam se um elemento é pintado ou visível. Em outras palavras, se um elemento tiver um preenchimento ou traço transparente alfa, ele será pintado mesmo que não possa ser visto.

Saber quando um elemento está pintado, visível ou nenhum dos dois é crucial para entender o impacto de cada valor pointer-events .

Tudo ou nada ou algo intermediário: os valores

pointer-events é uma propriedade CSS e um atributo de elemento SVG. Seu valor inicial é auto , o que significa que apenas as partes pintadas e visíveis receberão eventos de ponteiro. A maioria dos outros valores pode ser dividida em dois grupos:

  1. Valores que exigem que um elemento seja visível; e
  2. Valores que não.

painted , fill , stroke e all se enquadram na última categoria. Suas contrapartes dependentes de visibilidade - visiblePainted , visibleFill , visibleStroke e visible - se enquadram no primeiro.

A especificação SVG 2.0 também define um valor bounding-box . Quando o valor de pointer-events é bounding-box , a área retangular ao redor do elemento também pode receber eventos de ponteiro. Até o momento, apenas o Chrome 65+ suporta o valor bounding-box .

none também é um valor válido. Impede que o elemento e seus filhos recebam quaisquer eventos de ponteiro. A propriedade CSS pointer-events também pode ser usada com elementos HTML. Mas quando usado com HTML, apenas auto e none são valores válidos.

Como os valores pointer-events são mais bem demonstrados do que explicados, vejamos algumas demonstrações.

Aqui temos um círculo com um preenchimento e um traçado aplicado. É pintado e visível . O círculo inteiro pode receber eventos de ponteiro, mas a área fora do círculo não.

Veja a Pen Visible vs pintada em SVG por Tiffany Brown (@webinista) no CodePen.

Veja a Pen Visible vs pintada em SVG por Tiffany Brown (@webinista) no CodePen.

Desative o preenchimento, para que seu valor seja none . Agora, se você tentar passar o mouse, clicar ou tocar no interior do círculo, nada acontecerá. Mas se você fizer o mesmo para a área de traçado, os eventos de ponteiro ainda serão despachados. Alterar o valor de fill para none significa que esta área está visível , mas não pintada .

Vamos fazer uma pequena alteração em nossa marcação. Adicionaremos pointer-events="visible" ao nosso elemento circle , mantendo fill=none .

Veja a caneta Como adicionar eventos de ponteiro: tudo afeta a interatividade de Tiffany Brown (@webinista) no CodePen.

Veja a caneta Como adicionar eventos de ponteiro: tudo afeta a interatividade de Tiffany Brown (@webinista) no CodePen.

Agora, a área não pintada circundada pelo traço pode receber eventos de ponteiro.

Aumentando a área clicável de uma imagem SVG

Voltemos à imagem do início deste artigo. Nossa “ametista” é um elemento de path , em oposição a um grupo de polígonos, cada um com um stroke e um fill . Isso significa que não podemos simplesmente adicionar pointer-events="all" e encerrar o dia.

Em vez disso, precisamos aumentar a área de clique. Vamos usar o que sabemos sobre elementos pintados e visíveis. No exemplo abaixo, adicionei um retângulo à nossa marcação de imagem.

Veja a Caneta Aumentando a área de clique de uma imagem SVG por Tiffany Brown (@webinista) no CodePen.

Veja a Caneta Aumentando a área de clique de uma imagem SVG por Tiffany Brown (@webinista) no CodePen.

Mesmo que este retângulo não seja visto, ainda é tecnicamente visível (ou seja, visibility: visible ). Sua falta de preenchimento, no entanto, significa que não é pintado . Nossa imagem é a mesma. Na verdade, ainda funciona da mesma forma - clicar no espaço em branco ainda não aciona uma operação de navegação. Ainda precisamos adicionar um atributo pointer-events ao nosso elemento a . Usar os valores visible ou all funcionará aqui.

Veja a Caneta Aumentando a área de clique de uma imagem SVG por Tiffany Brown (@webinista) no CodePen.

Veja a Caneta Aumentando a área de clique de uma imagem SVG por Tiffany Brown (@webinista) no CodePen.

Agora a imagem inteira pode receber eventos de ponteiro.

Usar bounding-box eliminaria a necessidade de um elemento fantasma. Todos os pontos dentro da caixa delimitadora receberiam eventos de ponteiro, incluindo o espaço em branco delimitado pelo caminho. Mas, novamente: pointer-events="bounding-box" não é amplamente suportado. Até que seja, podemos usar elementos não pintados.

Usando pointer-events ao misturar SVG e HTML

Outro caso em que pointer-events podem ser úteis: usando SVG dentro de um botão HTML.

Veja a Pen Ovxmmy de Tiffany Brown (@webinista) no CodePen.

Veja a Pen Ovxmmy de Tiffany Brown (@webinista) no CodePen.

Na maioria dos navegadores — Firefox e Internet Explorer 11 são exceções aqui — o valor de event.target será um elemento SVG em vez de nosso botão HTML. Vamos adicionar pointer-events="none" à nossa tag SVG de abertura.

Veja o Pen How pointer-events: none pode ser usado com SVG e HTML por Tiffany Brown (@webinista) no CodePen.

Veja o Pen How pointer-events: none pode ser usado com SVG e HTML por Tiffany Brown (@webinista) no CodePen.

Agora, quando os usuários clicarem ou tocarem em nosso botão, o event.target fará referência ao nosso button .

Aqueles versados ​​em DOM e JavaScript notarão que usar a palavra-chave function em vez de uma função de seta e this em vez de event.target corrige esse problema. Usar pointer-events="none" (ou pointer-events: none; em seu CSS), no entanto, significa que você não precisa confirmar essa peculiaridade JavaScript específica na memória.

Conclusão

SVG suporta o mesmo tipo de interatividade que estamos acostumados com HTML. Podemos usá-lo para criar gráficos que respondem a cliques ou toques. Podemos criar áreas vinculadas que não aderem ao modelo de caixa CSS e HTML. E com a adição de pointer-events , podemos melhorar a maneira como nossos documentos SVG se comportam em resposta à interação do usuário.

O suporte do navegador para pointer-events SVG é robusto. Todos os navegadores que suportam SVG suportam a propriedade para documentos e elementos SVG. Quando usado com elementos HTML, o suporte é um pouco menos robusto. Não está disponível no Internet Explorer 10 ou seus antecessores, ou em qualquer versão do Opera Mini.

Acabamos de arranhar a superfície dos pointer-events nesta peça. Para um tratamento técnico mais aprofundado, leia a Especificação SVG. O MDN (Mozilla Developer Network) Web Docs oferece documentação mais amigável para desenvolvedores da Web para pointer-events , completo com exemplos.