PerfectVector
Por Irene Kim10 min de leitura

Texto foreignObject em SVG: corrija rótulos ausentes na exportação

Corrija rótulos SVG que aparecem no navegador, mas somem na exportação. Compare foreignObject com texto nativo, confira namespaces e preserve a arte existente.

Nesta página

Se as formas de um SVG sobreviverem à exportação, mas seus rótulos desaparecerem, inspecione o rótulo ausente em busca de <foreignObject>. Ele pode conter HTML que o navegador organiza corretamente, mas que o renderizador de destino não suporta. Substitua o rótulo afetado por <text> e <tspan> nativos do SVG, ou escolha uma forma de exportação que preserve sua aparência.

Primeiro abra o arquivo exportado exato em um navegador. Se o rótulo também estiver ausente ali, confira seu namespace, seus limites e seus estilos antes de culpar o importador. Preserve a arte original: traçar a imagem inteira é desnecessário quando apenas o contêiner de texto falhou.

Por que a imagem permanece enquanto seu rótulo desaparece

Um SVG pode misturar formas comuns com conteúdo de outro namespace XML. Uma montanha desenhada com <path> e um sol desenhado com <circle> são SVG nativo. Um parágrafo dentro de <foreignObject> pode ser HTML, com suas próprias regras de quebra de linha e layout. A referência de foreignObject do MDN descreve essa distinção.

A extensão .svg, portanto, não promete que todas as partes usem os mesmos recursos de renderização. Um destino pode desenhar a montanha e o sol omitindo o parágrafo HTML. Mudar a cor do texto ou aumentar a resolução da exportação não adicionará suporte a HTML nesse renderizador.

O que você vêO que verificar depoisCorreção provável
As formas aparecem nos dois lugares; os rótulos aparecem apenas no navegadorO rótulo ausente usa foreignObject?Substitua esse rótulo ou mude a forma de exportação
O rótulo HTML também está ausente no navegadorNamespace XHTML, limites explícitos, visibilidade e estilosCorrija primeiro o contêiner HTML
O texto nativo aparece com outra fonte ou comprimento de linhaDisponibilidade da fonte e posições de linha escolhidasResolva as fontes ou converta as letras finais em contornos
A maior parte do desenho está ausenteViewport, recorte e estrutura do documentoUse as verificações gerais de SVG vazio

Um pequeno teste: altere apenas o rótulo

Criamos um cartão SVG de 480 × 240 com um path, um circle e as palavras "Keep artwork and labels separate" (mantenha arte e rótulos separados). O primeiro arquivo usa um rótulo HTML. O segundo mantém as mesmas formas e substitui apenas o rótulo por texto nativo e três linhas explícitas.

Em nossa prévia no navegador, os dois rótulos apareceram. Renderizar os mesmos arquivos em PNG com sharp 0.34.4, usando seu librsvg 2.61.1 incluído, produziu o resultado abaixo: o rótulo HTML desapareceu, enquanto o nativo permaneceu. A saída com rótulo HTML também foi idêntica pixel a pixel a um arquivo de controle com o rótulo removido. Este é um teste desses arquivos e dessa versão do renderizador, não um veredito de compatibilidade para todos os editores.

Quatro renderizações do mesmo cartão ilustrado: os dois rótulos aparecem no navegador, enquanto o librsvg omite o rótulo HTML e mantém o texto SVG nativo
A arte permanece igual nos quatro casos. Apenas o rótulo HTML desaparece na saída do librsvg; o texto nativo usa quebras de linha explícitas.

O arquivo original é pequeno o suficiente para reproduzir. Salve isto como html-label.svg e abra-o em um navegador:

<svg xmlns="http://www.w3.org/2000/svg"
  width="480" height="240" viewBox="0 0 480 240">
  <rect width="480" height="240" rx="20" fill="#f5f1e7"/>
  <path d="M40 135Q90 15 140 135Z" fill="#087f75"/>
  <circle cx="90" cy="95" r="18" fill="#f4bc45"/>
  <foreignObject x="180" y="70" width="230" height="110">
    <div xmlns="http://www.w3.org/1999/xhtml"
      style="font: 28px/1.25 Arial, sans-serif; color: #172b34;">
      Keep artwork and labels separate
    </div>
  </foreignObject>
</svg>

Para o segundo arquivo, substitua todo o elemento foreignObject por este rótulo e salve-o como native-label.svg:

<text x="180" y="96" font-family="Arial, sans-serif"
  font-size="28" fill="#172b34">
  <tspan x="180" dy="0">Keep artwork</tspan>
  <tspan x="180" dy="35">and labels</tspan>
  <tspan x="180" dy="35">separate</tspan>
</text>

O valor x inicia cada linha na mesma posição horizontal. Os valores dy movem as linhas seguintes para baixo. Isso abre mão deliberadamente da quebra automática de HTML: o autor escolhe as quebras de linha e verifica se cabem. O MDN documenta o posicionamento de tspan, e o librsvg lista seus elementos SVG compatíveis, incluindo text e tspan.

Abra os dois arquivos pelo fluxo real de entrega, como seu conversor de imagens ou gerador de PDF. Compare o resultado salvo, não apenas a prévia da origem. Usar as mesmas dimensões do exemplo não garante as mesmas fontes em outra máquina.

Se o rótulo também estiver ausente no navegador

Confira o arquivo .svg serializado, não apenas a página que o criou. SVG embutido em HTML e um documento SVG independente são contextos de análise diferentes.

O exemplo coloca explicitamente o div em http://www.w3.org/1999/xhtml. O MDN observa que essa declaração de namespace é necessária para o conteúdo HTML em um documento SVG independente, mesmo quando um exemplo embutido em HTML pode omiti-la. Se você criar elementos em JavaScript, use o namespace adequado para o filho HTML; um div criado no namespace SVG não é um contêiner de parágrafo HTML.

Depois inspecione estas partes do rótulo:

  • Dê a foreignObject valores explícitos e positivos de width e height para a área pretendida do rótulo.
  • Mantenha suas coordenadas x e y dentro do desenho visível, com espaço para todas as linhas.
  • Confira display, visibility, opacidade e cor do texto no contêiner e em seus filhos.
  • Confirme que o arquivo exportado inclui os estilos necessários, em vez de depender da folha de estilo da página web ao redor.

No exemplo, todos os estilos do rótulo são embutidos e a caixa tem 230 unidades de largura por 110 de altura. Isso elimina o CSS externo como variável. Não torna foreignObject portátil para um renderizador que não possua esse recurso.

Para exportações do draw.io, converta os rótulos na origem

Se você ainda tem o diagrama editável, corrija a exportação dos rótulos nele antes de editar XML manualmente. A documentação atual de exportação do draw.io oferece Convert Labels to SVG (converter rótulos em SVG) para rótulos formatados compatíveis: selecione as formas ou conectores, abra a seção Advanced da aba Text e marque a caixa de seleção.

Essa opção tem limites. A documentação exclui dessa conversão rótulos com estruturas como tabelas, listas, links ou cores de fundo. Se a opção estiver indisponível, desativar Formatted Text (texto formatado) e Word Wrap (quebra automática de linha) é outro caminho documentado; talvez seja preciso inserir quebras de linha manuais e conferir o layout novamente.

Exporte uma nova cópia e reabra-a no aplicativo de destino. Ocultar um aviso "Text is not SVG" não converte o rótulo. Incorporar uma fonte resolve uma dependência de fonte, não a falta de suporte ao layout HTML.

Para um diagrama ilustrado, mantenha a arte importada separada dos rótulos. O guia de formas SVG personalizadas no draw.io aborda o lado da arte nesse fluxo.

Escolha o formato de texto para quem receberá o arquivo

Texto nativo é uma correção útil quando o destinatário precisa editar as palavras, mas ainda depende de fontes utilizáveis. Se o rótulo aparecer com a fonte errada, siga as verificações de fontes SVG em vez de tratá-lo como o mesmo problema de contêiner ausente.

Necessidade de entregaEscolha práticaO que verificar
Texto editáveltext nativo com posições de linha deliberadasFonte, comprimentos de linha e editor de destino
Formas fixas das letrasConverta as letras finais em contornos no editor de origemAparência correta; guarde um original editável
Layout rico apenas no navegadorMantenha foreignObject quando esse fluxo no navegador atender ao requisitoO arquivo real, embutido ou independente
Apenas aparênciaExporte um PNG de um renderizador que mostre o design completoDimensões em pixels e menor texto no tamanho de entrega

A conversão em contornos só funciona quando a ferramenta de origem consegue ver e converter as letras. Abrir uma exportação já incompleta e converter seus objetos restantes não restaura palavras ausentes desse documento importado. Um PNG preserva pixels, portanto é inadequado quando o destinatário precisa de palavras editáveis ou traçados vetoriais de corte.

Onde o PerfectVector se encaixa em um cartão ilustrado

Se a ilustração do cartão existe apenas como PNG ou JPG, o fluxo de clipart para SVG do PerfectVector pode preparar um candidato vetorial para essa arte. Mantenha o texto como um elemento separado no editor de design. Confira as bordas e os espaços internos da ilustração, adicione o rótulo e teste o arquivo montado no renderizador de destino.

O guia de vetorização de imagens explica como pixels viram traçados. O PerfectVector não corrige rótulos HTML em um SVG. Quando a ilustração já tem bons traçados, preserve-os e altere apenas o rótulo que falhou. Uma captura do rótulo ausente não contém letras para recuperar, e traçar letras visíveis criaria formas em vez de palavras editáveis.

Antes de enviar o SVG corrigido

  1. Reabra a cópia exportada em um navegador e no destino pretendido.
  2. Confirme que todos os rótulos, incluindo sua última linha, estão visíveis.
  3. Confira se a arte não se moveu nem mudou de tamanho.
  4. Verifique as fontes ou inspecione as letras convertidas em contornos no tamanho pretendido.
  5. Guarde a origem editável junto da cópia de entrega.

Perguntas frequentes

Por que o texto SVG aparece no Chrome, mas desaparece em uma exportação PNG? O rótulo pode ser HTML dentro de foreignObject, enquanto o renderizador PNG suporta apenas outro subconjunto de SVG. Confira a marcação do rótulo ausente e renderize uma versão de texto nativo pelo mesmo fluxo de exportação.

Adicionar o namespace XHTML corrige toda exportação foreignObject? Não. Ele corrige o namespace do conteúdo HTML em um SVG independente. O destino ainda precisa suportar esse conteúdo, e o rótulo ainda precisa de dimensões adequadas e estilos visíveis.

tspan pode quebrar texto como um parágrafo HTML? O exemplo usa linhas explícitas e deslocamentos verticais. Ele não reproduz o layout de parágrafos HTML. Escolha as quebras de linha para o espaço disponível e confira-as com a fonte do destino.

Devo vetorizar o cartão inteiro para recuperar seus rótulos? Preserve os traçados existentes e reconstrua o rótulo a partir de seu texto original. Vetorize apenas a arte que existe como pixels. Letras traçadas são geometria, portanto não preservam palavras editáveis.

Fontes

  1. MDN — foreignObject — Define conteúdo de outro namespace, atributos de geometria e o namespace XHTML em SVG independente.
  2. MDN — tspan — Explica o posicionamento de partes do texto SVG nativo.
  3. draw.io — Problemas de texto em SVG exportado — Documenta conversão de rótulos nativos, limites de formatação e configurações alternativas de exportação.
  4. GNOME — Recursos SVG e CSS compatíveis com Librsvg — Lista os elementos e atributos compatíveis com o renderizador.

Se sua ilustração ainda é um bitmap, prepare o clipart como SVG, inspecione suas formas e adicione o texto separadamente. Verifique ambos no arquivo exportado antes de entregá-lo.

Mais do blog

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