PerfectVector
Por Irene Kim

Ignore áreas SVG transparentes nos cliques do Konva

Faça áreas transparentes de imagens SVG ignorarem cliques no Konva. Reproduza a detecção pelo cache, teste furos e fundos e reconstrua a área ao mudar a origem.

13 min de leitura
Nesta página

Para que as áreas transparentes de uma Konva.Image ignorem cliques, espere a decodificação da imagem de origem, chame imageNode.cache(), depois imageNode.drawHitFromCache(0) e redesenhe a camada. O alfa da cena em cache, ou seja, a opacidade dos pixels, passa a determinar quais pixels da imagem participam da detecção de acertos.

Um nó de imagem normal pode receber eventos em todo o seu retângulo, inclusive em um furo vazio do SVG. O tutorial Image Events do Konva demonstra a alternativa baseada em alfa. Este artigo testa um SVG original vazado acima de um fundo clicável separado, de modo que um furo que deixa de capturar cliques da imagem tenha um alvo real por baixo para recebê-los.

Isso muda a área de interação do canvas. Não cria nós Konva.Path editáveis a partir do SVG nem muda as regras pointer-events do SVG no DOM.

Separe a imagem de sua área de acerto

Uma área de acerto é a região que o Konva usa para escolher o alvo de um evento. Sua forma pode ser diferente da arte visível. Em alguns aplicativos, um alvo retangular amplo é intencional; em outros, furos transparentes devem permitir selecionar um objeto inferior.

Interação desejadaPonto de partida
Selecionar a imagem inteira em qualquer ponto de seu retânguloComportamento de acerto padrão de Image
Deixar pixels transparentes alcançarem um nó abaixoArmazenar a imagem em cache e construir sua área de acerto a partir do alfa
Editar ou vincular ações independentes a regiões vetoriais individuaisEscolher caminhos Konva separados e definir seu comportamento
Controlar alvos do ponteiro dentro de SVG inline no DOMUsar o guia separado de pointer-events em SVG

A API Shape atual recebe um inteiro alphaThreshold de 0 a 255; o padrão é 0. Passe um número, não uma função de callback. Isso é diferente do filtro visual Threshold. O exemplo usa 0 com interiores totalmente opacos e furos totalmente transparentes; não estabelece um limiar preferível para sombras suaves ou bordas com antisserrilhamento.

1. Salve duas entradas SVG completas

Crie uma pasta vazia. Salve este emblema original vazado como hollow.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="180" viewBox="0 0 240 180">
  <path fill="#315d6f" fill-rule="evenodd"
        d="M20 30 L180 20 L215 60 L195 150 L35 160 L10 110 Z
           M80 65 L145 55 L160 110 L95 125 Z"/>
</svg>

O subcaminho interno cria um furo pela regra de preenchimento par-ímpar. Salve a mesma forma externa sem esse subcaminho como filled.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="180" viewBox="0 0 240 180">
  <path fill="#315d6f" d="M20 30 L180 20 L215 60 L195 150 L35 160 L10 110 Z"/>
</svg>

O segundo arquivo é o controle de mudança da origem. Ele pinta a posição que antes estava vazia. Nenhum dos arquivos contém um retângulo de fundo branco ou bitmap incorporado.

2. Carregue, armazene em cache e registre os alvos reais

O exemplo usa Konva 10.9.0. Salve estes três arquivos ao lado dos dois SVGs. O HTML carrega essa versão fixa da compilação para navegador; em um projeto controlado, você pode servir a mesma compilação localmente.

Salve reader.html:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Konva transparent image hit comparison</title>
<link rel="stylesheet" href="reader.css">
<main>
<h1>Transparent artwork: which node gets the click?</h1>
<p class="banner"><strong id="version">Loading Konva…</strong>. Original same-origin SVGs, actual Konva.Image nodes, and a separately clickable background. These are canvas hit pixels, not editable SVG path nodes. Desktop click test only; no mobile or accessibility audit.</p>
<div class="grid">
<section class="panel"><h2>1. Default rectangular hit</h2><div class="stage" id="default"></div><p>The hollow image still catches its transparent center and corner.</p><pre class="log" id="default-log"></pre></section>
<section class="panel"><h2>2. Cached alpha hit region</h2><div class="stage" id="alpha"></div><p>cache() then drawHitFromCache(0): the center and corner reach the background.</p><pre class="log" id="alpha-log"></pre></section>
<section class="panel"><h2>3. Opaque image fill</h2><div class="stage" id="fill"></div><p>A white fill behind this image is part of its cached scene. Its formerly empty pixels receive image hits.</p><pre class="log" id="fill-log"></pre></section>
<section class="panel"><h2>4. Replaced source, rebuilt cache</h2><div class="stage" id="updated"></div><p>The original hole is painted in filled.svg. Clear, replace, cache, and rebuild the hit region.</p><pre class="log" id="updated-log"></pre></section>
</div>
<p>Click these stage coordinates in each panel: solid (125,110), hole (195,130), transparent corner (305,55), and outside the image (20,20). The corner is inside the image viewport but outside its painted shape. Logs report actual click targets.</p>
 
</main>
<script src="https://unpkg.com/konva@10.9.0/konva.min.js"></script>
<script type="module" src="reader.js"></script>
</html>

Salve reader.css:

body { margin: 32px; font: 16px/1.55 Arial, sans-serif; color: #183a42; background: #edf2ef; }
main { max-width: 1080px; margin: auto; }
h1 { font-size: 32px; margin-bottom: 12px; }
h2 { margin: 0 0 12px; font-size: 22px; }
p { margin: 10px 0; }
.banner { background: #dce8e4; padding: 18px; border-left: 5px solid #315d6f; }
.grid { display: grid; grid-template-columns: repeat(2, minmax(460px, 1fr)); gap: 20px; margin: 24px 0; }
.panel { background: white; padding: 20px; border: 1px solid #d1dbd5; border-radius: 12px; }
.stage { width: 420px; height: 260px; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; background: #f8faf7; padding: 12px; }
table { border-collapse: collapse; width: 100%; margin-top: 20px; }
th, td { border-bottom: 1px solid #c9d5ce; padding: 10px; text-align: left; }
.log { min-height: 88px; margin-bottom: 0; font-size: 13px; }

Salve reader.js:

const source = new Image();
source.src = './hollow.svg';
await source.decode();
const replacement = new Image();
replacement.src = './filled.svg';
await replacement.decode();
 
const clicks = [];
const scenes = [];
function makeScene(id, mode) {
  const stage = new Konva.Stage({ container: id, width: 420, height: 260 });
  const layer = new Konva.Layer();
  stage.add(layer);
  const background = new Konva.Rect({
    id: `${id}-background`, width: 420, height: 260, fill: '#eadfcd'
  });
  const artwork = new Konva.Image({
    id: `${id}-image`, image: source, x: 80, y: 40, width: 240, height: 180
  });
  if (mode === 'fill') artwork.fill('#ffffff');
  layer.add(background, artwork);
  if (mode !== 'default') {
    artwork.cache();
    artwork.drawHitFromCache(0);
  }
  layer.draw();
  const beforeUpdate = stage.getIntersection({ x: 195, y: 130 }).id();
  if (mode === 'update') {
    artwork.clearCache();
    artwork.image(replacement);
    artwork.cache();
    artwork.drawHitFromCache(0);
    layer.draw();
  }
  stage.on('click', (event) => {
    const point = stage.getPointerPosition();
    const record = {
      scene: id, x: point.x, y: point.y,
      target: event.target.id(), trusted: event.evt.isTrusted
    };
    clicks.push(record);
    document.getElementById(`${id}-log`).textContent +=
      `(${Math.round(point.x)}, ${Math.round(point.y)}) → ${record.target}\n`;
    document.dispatchEvent(new CustomEvent('fixture-click-recorded'));
  });
  const scene = { id, stage, artwork, beforeUpdate };
  scenes.push(scene);
  return scene;
}
makeScene('default', 'default');
makeScene('alpha', 'alpha');
makeScene('fill', 'fill');
makeScene('updated', 'update');
document.getElementById('version').textContent = `Konva ${Konva.version}`;

Sirva a pasta por HTTP em vez de abrir o HTML como arquivo local:

python -m http.server 8000

Abra http://localhost:8000/reader.html e espere os quatro palcos aparecerem. O SVG de 240 × 180 fica nas coordenadas (80,40) de cada palco de 420 × 260. Cada fundo é um Konva.Rect separado que recebe eventos, abaixo da imagem. O ouvinte de clique do palco informa event.target.id(), que identifica o nó Konva escolhido, não apenas o elemento canvas no DOM.

await source.decode() é executado antes da criação do cache. Crie o cache depois que a origem real estiver pronta, não enquanto a imagem ainda carrega. A API Node documenta os métodos de criação e limpeza do cache.

3. Clique na área sólida, no furo, no canto e no fundo

Teste as quatro posições listadas abaixo dos painéis. São coordenadas dentro de cada palco, não medidas a partir da janela do navegador.

PosiçãoCoordenada no palcoO que testa
Arte sólida125,110Um ponto opaco bem dentro do emblema
Furo original195,130Um interior transparente em hollow.svg
Canto transparente305,55Dentro do retângulo da imagem, fora da silhueta pintada
Fora da imagem20,20O fundo clicável separado

A tabela abaixo registra o tipo de alvo testado. Os logs incluem o prefixo de cada painel, como alpha-background.

ConfiguraçãoÁrea sólidaFuro originalCanto transparenteFora da imagem
Imagem padrãoImagemImagemImagemFundo
Área de acerto alfa em cacheImagemFundoFundoFundo
Imagem em cache com preenchimento branco opacoImagemImagemImagemFundo
Origem substituída e cache reconstruídoImagemImagemFundoFundo
Comparação real do Konva no navegador com acertos retangulares padrão, acertos por alfa em cache, preenchimento opaco e origem substituída, incluindo IDs registrados dos alvos de clique
Palcos reais do Konva 10.9.0 com arte SVG original e alvos de clique em desktop registrados. A imagem vazada baseada em alfa deixa os cliques no furo e no canto alcançarem o fundo separado. Um preenchimento opaco na imagem e uma origem substituta pintada mudam esses resultados.

O teste no navegador usou cliques reais do ponteiro nas 16 posições e registrou a confiança nativa do evento, as coordenadas do palco e os IDs dos alvos. Também conferiu hashes dos arquivos de origem, decodificação das imagens, dimensões dos palcos e imagens, resultados públicos de interseção e amostras nativas de alfa do canvas renderizado de cada nó de imagem.

No furo original, o alfa do nó de imagem vazada era 0. Os controles com preenchimento opaco e origem substituída tinham alfa 255 ali. O fundo separado da página não tornou a própria imagem vazada opaca: ele pertencia a outro nó Konva abaixo dela. São amostras internas, longe das bordas com antisserrilhamento.

Este é um teste em um navegador desktop com SVGs originais simples e palcos sem transformações. Não comprova comportamento móvel ou de toque, interação por teclado, uma matriz entre navegadores, ganhos de desempenho ou um limiar adequado para toda imagem com bordas suaves. Repita o teste de clique no tamanho exibido e nas transformações reais do seu aplicativo.

4. Reconstrua o cache quando a origem mudar

O quarto painel começa com a origem vazada e sua área de acerto alfa. Em seguida, limpa o cache, instala a imagem substituta já decodificada, cria o cache novamente e reconstrói a área de acerto. Depois dessa sequência, a posição do furo original passa do fundo para a imagem.

O cache é uma captura renderizada. Após uma mudança que afeta os pixels renderizados, atualize juntos a cena em cache e sua área de acerto baseada em alfa. Não suponha que atribuir outra imagem atualizou uma área de acerto já armazenada. Para uma substituta carregada de forma assíncrona, espere sua decodificação antes da sequência do exemplo.

O terceiro painel isola outra causa: artwork.fill('#ffffff') pinta um retângulo opaco atrás da imagem como parte daquele mesmo nó. Construir a área de acerto a partir dessa cena em cache inclui a região pintada. Remova um preenchimento indesejado do nó de imagem e depois reconstrua cache e área de acerto. Uma região aparentemente branca no arquivo de origem também pode ser pintura realmente opaca; inspecione a transparência antes de culpar a detecção de acertos.

Diagnostique separadamente falhas de leitura e de seleção de alvo

SintomaO que conferir primeiro
O furo ainda registra a imagemConfirme que o cache foi criado após a decodificação, a área de acerto foi reconstruída e nenhum preenchimento opaco ou fundo da origem cobre o furo
A arte mudou, mas os cliques seguem uma forma antigaLimpe e reconstrua o cache da cena e a área de acerto alfa após mudar a origem
Aparece um erro de leitura de pixels ou canvas contaminadoConfira a origem da imagem e os cabeçalhos da resposta antes de interpretar o resultado do teste de acerto
A imagem inteira deixa de receber eventosConfira listening, visibilidade, ordem das camadas e se outro nó está por cima
Um furo alcança o palco em vez de um objeto inferiorConfirme que um objeto previsto que recebe eventos realmente existe abaixo daquele ponto
Cliques no canvas funcionam, mas o teclado nãoProjete controles de teclado e semântica separadamente; pixels de acerto alfa não os fornecem

Esta amostra serve os dois SVGs pela mesma origem da página. Imagens de outra origem exigem um canvas sem contaminação de origem para a leitura de pixels. O guia de canvas contaminado do Konva explica o uso de crossOrigin junto a um servidor que permita a solicitação CORS. Definir apenas crossOrigin = 'anonymous' não concede acesso quando o servidor não permite. Este artigo não executou um caso de falha entre origens.

Mudar o CSS pointer-events no canvas externo não escolhe quais pixels dentro de uma Konva.Image atingem seus nós internos. Separe a seleção de alvos no canvas da seleção de ponteiro em SVG no DOM. Preserve também o master SVG: um mapa de acerto em cache é dado de interação baseado em pixels, não um documento vetorial substituto.

Separe a recuperação da arte da ligação dos eventos

Se seu aplicativo precisa apenas de posicionamento de imagem e acertos baseados em alfa, uma imagem raster transparente adequada talvez já baste. Se só resta um PNG ou JPG e o aplicativo também precisa de geometria de caminhos editável, o fluxo de imagem para vetor do PerfectVector pode ajudar a recuperar um SVG candidato. Inspecione a silhueta e os furos, depois escolha a representação no Konva e implemente seus eventos. Este exemplo usou SVGs nativos originais e não realizou uma conversão com o PerfectVector.

A vetorização não instala ouvintes, não cria controles acessíveis, não escolhe alvos de clique nem mantém caches sincronizados. Se já existe um master SVG, corrija diretamente o código de interação. Para um arquivo que inesperadamente contém uma imagem retangular completa, use a verificação de raster incorporado em SVG antes de supor que seu conteúdo sejam caminhos editáveis separados.

Perguntas frequentes

Por que pixels transparentes da minha imagem Konva recebem cliques? Um nó Image padrão pode usar sua área retangular para acertos. Quando a origem estiver pronta, crie o cache e use drawHitFromCache com um limiar alfa numérico adequado; depois redesenhe e teste os alvos reais.

Qual argumento drawHitFromCache recebe? A API atual aceita um limiar alfa inteiro opcional de 0 a 255, com padrão 0. O exemplo testado passa 0. Não passa callback nem usa o filtro visual Threshold.

Por que um preenchimento branco torna meu furo SVG clicável de novo? Um preenchimento opaco no nó Image passa a fazer parte da cena em cache. O alfa armazenado inclui essa região pintada. Remova o preenchimento indesejado e reconstrua o cache da cena e a área de acerto.

Uma área de acerto alfa torna os caminhos SVG editáveis individualmente? Não. A arte continua sendo um único nó Image. Use nós Path separados adequados e um modelo explícito de cena quando seu aplicativo precisar controlar regiões vetoriais individuais.

Fontes

  1. Konva: Image Events — Comportamento padrão de acerto em imagens e geração de uma área de acerto a partir da arte em cache.
  2. Konva: API Shape — Parâmetro numérico alphaThreshold atual e seu intervalo.
  3. Konva: API Node — Criação e limpeza do cache, alvos de eventos e métodos públicos dos nós.
  4. Konva: Guia de canvas contaminado — Restrições de origem, CORS e falhas de leitura dos pixels.
  5. Konva: SVG no canvas — Renderização da imagem inteira versus caminhos vetoriais construídos separadamente.

Quando faltar geometria editável, prepare um SVG candidato com o PerfectVector, inspecione seus furos e depois teste separadamente os alvos de clique pretendidos no Konva e as atualizações do cache.

Mais do blog

PerfectVector

Recomece com um SVG mais limpo
e fácil de editar

Sem cartão de crédito