PerfectVector
Por Irene Kim10 min de leitura

Imagens SVG no Graphviz: arte de nós portátil

Adicione arte SVG a um nó Graphviz, inspecione sua referência de imagem e teste um pacote completo de recursos contra um diagrama movido e uma cópia autossuficiente.

Nesta página

Um diagrama Graphviz pode conter nós e setas vetoriais enquanto a arte personalizada dos nós ainda aponta para um arquivo de imagem separado. Se essa arte desaparecer depois que você mover o SVG, inspecione a referência de imagem gerada antes de mudar o desenho. A parte ausente pode estar no pacote de entrega.

Na saída SVG testada abaixo, o Graphviz mantém motif.svg como uma imagem vinculada. O pacote completo a renderiza; o diagrama movido sozinho a perde. Uma cópia explicitamente empacotada inclui os bytes da arte e a renderiza no mesmo teste de navegador. Essa etapa de empacotamento ainda mantém um elemento image SVG, em vez de transformar o motivo em traçados nativos do grafo.

Guarde a origem DOT para os nomes e relacionamentos dos nós. Mantenha o original da arte separado e teste a saída exata no visualizador ou fluxo de publicação que a receberá.

Diferencie o nó, sua arte e sua referência de arquivo

O atributo image do Graphviz nomeia a arte exibida dentro de um nó. Ele não substitui a identidade nem os relacionamentos desse nó no grafo. A documentação exige dimensões de origem; para imagens SVG, forneça width e height explícitos com unidades adequadas.

O motivo original aqui é um desenho de dois traçados com um espaço de coordenadas de 96 por 64. Suas dimensões externas são 96pt por 64pt. O nó ao redor e a seta pertencem ao Graphviz.

ParteMantida emO que pode dar errado
Nomes, rótulos e arestas dos nósOrigem DOTRelacionamentos incorretos do grafo ou texto errado
Motivo personalizadoOriginal SVG da arteDimensões ausentes, detalhes inadequados ou proporções erradas
Vínculo do diagrama ao motivoReferência de imagem SVG exportadaArte ausente no caminho resolvido
Posicionamento e tamanho finaisSaída do renderizador e visualizador de destinoRecorte, distorção ou dependências incompatíveis

Um elemento image pode apontar para arte SVG ou para pixels. Para investigar uma origem raster, use o diagnóstico separado de imagens incorporadas em SVG. Um nome de arquivo terminado em .svg não basta para comprovar o conteúdo de nenhum dos arquivos.

Execute um pequeno exemplo com um renderizador explícito

Usamos @viz-js/viz 3.31.0, uma compilação WebAssembly que informa Graphviz 16.1.0, com o mecanismo de layout dot e a saída SVG integrada. Este é um teste dessa compilação e desse renderizador, não uma afirmação de que toda instalação do Graphviz carrega imagens de forma idêntica.

Em uma nova pasta de projeto Node.js, instale o pacote com a versão fixada:

npm install @viz-js/viz@3.31.0

Salve a arte original como motif.svg:

<svg xmlns="http://www.w3.org/2000/svg"
     width="96pt" height="64pt" viewBox="0 0 96 64">
  <path fill="#173b40" fill-rule="evenodd"
    d="M48 4C70 4 88 17 88 32S70 60 48 60S8 47 8 32S26 4 48 4Z
       M48 14C31 14 19 22 19 32S31 50 48 50S77 42 77 32S65 14 48 14Z"/>
  <path fill="#28bfa3"
    d="M43 20H53V27H60V37H53V44H43V37H36V27H43Z"/>
</svg>

Salve o grafo como diagram.dot:

digraph G {
  graph [rankdir=LR, bgcolor="white", margin=0.1];
  node [shape=box, fontname="Arial", fontsize=16,
        color="#173b40", penwidth=1.5,
        fixedsize=true, width=1.8, height=1.1];
  artwork [label="", image="motif.svg", imagescale=true];
  review [label="Review"];
  artwork -> review [color="#173b40", penwidth=1.5];
}

Depois salve isto como render.mjs e execute node render.mjs nessa pasta:

import { instance } from '@viz-js/viz';
import fs from 'node:fs';
 
const viz = await instance();
const dot = fs.readFileSync('diagram.dot', 'utf8');
const svg = viz.renderString(dot, {
  engine: 'dot',
  format: 'svg',
  images: [{ name: 'motif.svg', width: '96pt', height: '64pt' }]
});
 
fs.mkdirSync('bundle', { recursive: true });
fs.copyFileSync('motif.svg', 'bundle/motif.svg');
fs.writeFileSync('bundle/diagram.svg', svg);
process.stdout.write(`Graphviz ${viz.graphvizVersion}\n`);

A documentação da API do Viz.js descreve a opção images como informações de tamanho da imagem. Fornecê-la informa ao layout sobre essa arte nomeada; isso não insere os bytes do arquivo no resultado. As unidades explícitas evitam tratar um número sem unidade como pixels CSS. A API usa pontos para dimensões sem unidades.

Para uma instalação nativa do Graphviz, a documentação oficial de image descreve recursos locais de imagem e dimensões lidas do arquivo de origem. Não copie a configuração de metadados WebAssembly para um comando nativo presumindo que ele tenha o mesmo mecanismo de carregamento.

Inspecione o que o renderizador escreveu

Nosso SVG gerado contém este elemento:

<image xlink:href="motif.svg"
       width="118.8px" height="79.2px"
       preserveAspectRatio="xMinYMin meet"
       x="5.4" y="-79.2"/>

As dimensões e a posição são valores observados neste exemplo. A parte que controla a entrega é xlink:href="motif.svg": o resultado ainda precisa de um recurso nesse caminho relativo.

Copie apenas diagram.svg para outra pasta e deixe a arte para trás. Compare-o com o pacote completo. Servimos ambas as pastas por HTTP local e exibimos cada SVG como documento por meio de um elemento HTML object.

Três diagramas SVG reais do Graphviz: arte presente em seu pacote completo de recursos, ausente após o diagrama ser movido sozinho e presente em uma cópia com os bytes da imagem SVG incorporados
O arquivo do meio tem a mesma geometria do grafo e referência de arte que o arquivo à esquerda. Seu motivo está ausente no caminho resolvido. A cópia à direita inclui explicitamente essa arte como uma URL de dados SVG.

As caixas dos nós e a seta geradas permanecem presentes quando o motivo vinculado está ausente. Recriar o layout do grafo não fornece o arquivo ausente. Restaure o local esperado do recurso, entregue o pacote completo ou escolha uma etapa de empacotamento adequada ao destino.

Abrir um SVG como documento e exibi-lo por meio de um img HTML são testes diferentes. A orientação do MDN sobre SVG como imagem explica que contextos de imagem podem restringir recursos externos, enquanto URLs de dados podem incorporá-los. As restrições de contexto de imagem descritas não se aplicam a documentos SVG diretos nem à incorporação de documentos por object e iframe. Verifique o contexto de entrega que você realmente usa.

Empacote explicitamente este motivo simples

Para este motivo original autossuficiente, o script a seguir substitui exatamente uma referência conhecida pelos bytes SVG do arquivo. Salve-o como package.mjs e execute-o após a renderização:

import fs from 'node:fs';
 
const svg = fs.readFileSync('bundle/diagram.svg', 'utf8');
const needle = 'xlink:href="motif.svg"';
if (svg.split(needle).length !== 2) {
  throw new Error('Expected exactly one motif reference');
}
 
const data = 'data:image/svg+xml;base64,' +
  fs.readFileSync('bundle/motif.svg').toString('base64');
const packaged = svg.replace(needle, `xlink:href="${data}"`);
fs.writeFileSync('self-contained.svg', packaged);

Este é um exemplo específico de empacotamento, não uma ferramenta geral de incorporação SVG. Ele lida com a referência conhecida nesta saída e com um motivo que não possui fontes externas, imagens, folhas de estilo ou outras dependências. Artes mais complexas precisam de sua própria verificação de dependências.

A cópia empacotada foi renderizada com o motivo presente em nosso teste de navegador. Comparar as duas strings de saída após mascarar o valor da referência de imagem mostrou geometria idêntica do grafo. O arquivo ainda contém um elemento image; sua referência agora começa com data:image/svg+xml;base64,.

Incorporar bytes de imagem SVG pode remover essa dependência do caminho do arquivo, mantendo a origem vetorial da arte. Isso não transforma a arte em uma forma nativa de nó Graphviz, não adiciona pontos de conexão dentro dela nem garante que outro editor exponha seus traçados diretamente. Teste o comportamento de importação no destino.

Evite também confundir svg_inline com incorporação de imagem. A documentação de saída SVG do Graphviz descreve essa opção como saída sem cabeçalho para inclusão em HTML. No mesmo grafo, selecionar svg_inline ainda produziu a referência motif.svg. O modo de saída não empacotou a arte.

Separe dimensões e escala da portabilidade

A referência de imagescale do Graphviz distingue o ajuste da imagem dentro do nó do tamanho natural da origem. Neste exemplo, imagescale=true escala a imagem uniformemente para caber. A opção both escala largura e altura separadamente, o que pode mudar as proporções.

Se o motivo aparecer distorcido, inspecione a opção de escala. Se apenas uma parte aparecer, inspecione seus próprios limites e o espaço disponível no nó. Se desaparecer após mover o arquivo, inspecione primeiro o caminho do recurso. O guia de tamanho SVG explica a diferença entre tamanho declarado e coordenadas do desenho.

SintomaPrimeira verificaçãoCorreção a tentar
A arte desaparece após mover o diagramaReferência de imagem gerada e localização relativa do recursoRestaure o pacote ou empacote explicitamente a origem testada
O layout do grafo é executado, mas a arte está ausenteDimensões de origem e configuração de imagem específica da compilaçãoConfirme o arquivo e os metadados de imagem esperados por essa compilação
O motivo parece distorcidoConfiguração imagescale e proporções pretendidasUse ajuste uniforme quando não quiser distorção
O SVG funciona diretamente, mas falha em uma página webSe a página usa contexto de imagem ou de documentoTeste a forma de incorporação compatível e sua política de recursos
A saída difere após mudar de renderizadorRenderizador escolhido e sua estrutura SVGInspecione novamente o XML exportado e a aparência final

A página oficial de saída SVG observa que a saída Cairo pode diferir da saída SVG integrada na legibilidade do XML e na possibilidade de transformação. Não testamos Cairo aqui. Mantenha o renderizador explícito em um projeto reproduzível e repita a verificação de empacotamento ao mudá-lo.

Recupere a arte antes da montagem quando sua origem for perdida

O PerfectVector pode ajudar quando um motivo ilustrativo adequado existe apenas como PNG ou digitalização. Seu fluxo de recuperação de arte científica fornece um candidato vetorial para inspecionar antes do uso. Recorte o motivo, verifique sua silhueta e seus espaços vazios e confira os limites e as dimensões do SVG baixado antes de adicioná-lo ao grafo.

Essa recuperação não reconstrói relacionamentos entre nós, significados de setas nem rótulos DOT. Mantenha-os na origem do grafo. Use o SVG original quando disponível, redesenhe um símbolo simples quando isso for mais fácil de manter e preserve fotografias como imagens raster. A visão geral da vetorização de imagens explica o limite da recuperação.

Outras ferramentas de diagramas empacotam arte personalizada de formas diferentes. O guia de ícones do Mermaid aborda dados de ícones registrados, enquanto o guia de arte SVG personalizada no draw.io diferencia uma imagem importada de um stencil nativo. Leve os requisitos do destino para a preparação da arte.

Perguntas frequentes

A saída SVG do Graphviz inclui automaticamente a imagem do meu nó? Na saída SVG integrada testada, o diagrama contém uma referência de imagem ao arquivo separado motif.svg. Inspecione sua própria saída e entregue suas dependências ou use uma etapa de empacotamento testada.

svg_inline mescla os traçados de uma imagem SVG no grafo? Não. É um modo de saída sem cabeçalho para inclusão em HTML. Em nosso teste, ele manteve a referência externa motif.svg.

Um SVG autossuficiente é o mesmo que geometria nativa editável de nó? Não. O exemplo empacotado mantém um elemento image contendo bytes SVG. A estrutura do grafo permanece em DOT, e o editor de destino determina como expõe essa arte.

Fontes

  1. Graphviz — image — Recursos locais de imagem de nó e dimensões SVG exigidas.
  2. Graphviz — imagescale — Ajuste uniforme e escala independente de largura e altura.
  3. Graphviz — Saída SVG — Saída integrada e Cairo, além do significado de svg_inline.
  4. Viz.js — API — Metadados de tamanho de imagem, unidades explícitas e chamadas de renderização SVG.
  5. MDN — SVG como imagem — Restrições de recursos externos em contextos de imagem e distinção em relação à incorporação de documentos.

Teste um nó no fluxo de entrega antes de preparar uma biblioteca inteira de arte. Se apenas um motivo raster tiver restado, prepare um candidato de arte SVG, inspecione seus espaços e proporções, adicione-o ao grafo DOT e verifique a saída movida ou empacotada no visualizador de destino.

Mais do blog

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