Imagens SVG em nós Cytoscape.js: ajuste e margens
Ajuste arte SVG personalizada dentro de nós Cytoscape.js com um exemplo funcional. Compare espaço vazio, contain e cover; confira o carregamento e a posição dos rótulos.
Nesta página
Use uma URL de imagem SVG no estilo background-image do nó e escolha o ajuste para a arte que deseja mostrar. Se o emblema carrega, mas parece minúsculo, examine o espaço vazio na viewport do SVG antes de ampliar o nó do grafo. Se suas pontas desaparecem, compare as proporções da imagem com as do nó e confira o recorte.
O Cytoscape.js documenta fundos SVG de nós, incluindo os ajustes contain, cover e none. Este guia usa um emblema original de um caminho para separar os limites da origem da estilização do grafo. Mantenha o original editável da arte junto da configuração do grafo.
Separe a imagem de origem do nó do grafo
Há três caixas para examinar: os limites desenhados da arte, a viewport da imagem SVG e o corpo do nó. O viewBox SVG define o retângulo de coordenadas de origem mapeado para sua viewport. Ele pode incluir muito mais espaço do que o desenho visível.
Nossa origem com margens reduzidas mede 120 × 60, com o emblema coral indo de x=6 a x=114 e de y=6 a y=54. A abertura central faz parte do mesmo caminho:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>
<svg xmlns="http://www.w3.org/2000/svg"
width="120" height="60" viewBox="0 0 120 60">
<path fill="#f36f59" fill-rule="evenodd"
d="M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z"/>
</svg>A variante com margens maiores muda somente as dimensões externas do SVG e o viewBox:
<svg xmlns="http://www.w3.org/2000/svg"
width="200" height="140" viewBox="-40 -40 200 140">Mantenha o mesmo cabeçalho, caminho e tag de fechamento. Os dois arquivos desenham coordenadas de caminho idênticas. O segundo as envolve com mais espaço vazio na origem. Esse espaço é redimensionado junto com a imagem, portanto mudar o ajuste do fundo não substitui de forma confiável a escolha de limites adequados na origem. O guia de caixa delimitadora SVG ajuda quando a viewport do arquivo e a arte visível não correspondem.
Execute o exemplo de quatro casos
Testamos o Cytoscape.js 3.34.3 com um pacote oficial de navegador fixado nessa versão e servido localmente. Salve o pacote dessa tag de lançamento como cytoscape-3.34.3.min.js ao lado do example.html abaixo. Sirva a pasta por HTTP local, por exemplo com python3 -m http.server 8000, e abra http://localhost:8000/example.html.
O exemplo codifica o SVG original em uma URI de dados. encodeURIComponent() escapa caracteres de URI, incluindo o # da nossa cor de preenchimento. A orientação SVG da biblioteca recomenda essa codificação em vez de Base64, além do cabeçalho XML mostrado aqui. É um emblema independente, sem fontes ou imagens externas.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>SVG node fit comparison</title>
<style>
body { font: 16px system-ui; margin: 20px; }
#cy { width: 1100px; height: 250px; border: 1px solid #ddd; }
#status { white-space: pre-wrap; }
</style>
<div id="cy"></div>
<pre id="status">Loading images</pre>
<script src="cytoscape-3.34.3.min.js"></script>
<script>
const header = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg>';
const path = 'M6 30L30 6H90L114 30L90 54H30Z M50 20H70V40H50Z';
function artwork(padded) {
const width = padded ? 200 : 120;
const height = padded ? 140 : 60;
const viewBox = padded ? '-40 -40 200 140' : '0 0 120 60';
return header + `<svg xmlns="http://www.w3.org/2000/svg"
width="${width}" height="${height}" viewBox="${viewBox}">
<path fill="#f36f59" fill-rule="evenodd" d="${path}"/></svg>`;
}
const cases = [
['tight contain', false, 'contain'],
['tight cover', false, 'cover'],
['padded contain', true, 'contain'],
['padded cover', true, 'cover']
].map(([label, padded, fit]) => ({
label, fit,
image: 'data:image/svg+xml;utf8,' + encodeURIComponent(artwork(padded))
}));
Promise.all(cases.map(item => new Promise((resolve, reject) => {
const image = new Image();
image.onload = () => resolve({
label: item.label,
width: image.naturalWidth,
height: image.naturalHeight
});
image.onerror = () => reject(new Error(item.label + ' failed to load'));
image.src = item.image;
}))).then(loaded => {
cytoscape({
container: document.getElementById('cy'),
elements: cases.map((item, index) => ({
data: { id: 'n' + index, ...item },
position: { x: 110 + index * 260, y: 95 }
})),
style: [{ selector: 'node', style: {
width: 120, height: 80, padding: 0, shape: 'rectangle',
'background-color': '#f1f3f5',
'background-image': 'data(image)',
'background-fit': node => node.data('fit'),
'background-width': 'auto', 'background-height': 'auto',
'background-width-relative-to': 'inner',
'background-height-relative-to': 'inner',
'background-position-x': '50%', 'background-position-y': '50%',
'background-repeat': 'no-repeat', 'background-clip': 'node',
'border-width': 1, 'border-color': '#222',
label: 'data(label)', 'text-valign': 'bottom',
'text-halign': 'center', 'text-margin-y': 10, 'font-size': 12
}}],
layout: { name: 'preset', fit: false },
zoom: 1, pan: { x: 0, y: 0 },
userZoomingEnabled: false, userPanningEnabled: false,
boxSelectionEnabled: false
});
document.getElementById('status').textContent =
'Cytoscape ' + cytoscape.version + '\n' +
JSON.stringify(loaded, null, 2);
}).catch(error => {
document.getElementById('status').textContent = error.message;
});
</script>
</html>O bloco de estado informa as dimensões das imagens pré-carregadas antes da inicialização do grafo. naturalWidth lê a largura intrínseca da imagem, corrigida pela densidade, em pixels CSS, como descreve a MDN. Neste arquivo de teste, as imagens com margens reduzidas informaram 120 × 60 e as com margens maiores, 200 × 140. São dimensões de imagem, não medidas do caminho coral.
Compare o que muda no mesmo tamanho de nó
Os quatro nós do modelo medem 120 × 80, com preenchimento interno do nó igual a zero. Examinamos o arquivo original no Chrome com zoom de grafo 1 e 1.5. O estilo do nó continuou 120 × 80; suas dimensões renderizadas informadas passaram a 180 × 120 no zoom 1.5. Foi uma comparação estática nesse navegador, não um teste de compatibilidade ou desempenho de zoom.
| Origem e ajuste | Aparência observada neste arquivo de teste |
|---|---|
| Margens reduzidas, contain | Emblema completo, com as extremidades pontudas visíveis |
| Margens reduzidas, cover | Emblema maior com pontas esquerda e direita cortadas no nó |
| Margens maiores, contain | Emblema menor cercado por bastante espaço vazio |
| Margens maiores, cover | Um pouco maior que o caso anterior, ainda muito menor que os casos com margens reduzidas |
A origem com margens reduzidas tem proporção de imagem 2:1, enquanto o nó tem 1.5:1. Ajustar a imagem inteira de 120 × 60 dentro de 120 × 80 deixa espaço vertical. Cobrir esse nó amplia a imagem para 160 × 80 antes do recorte, portanto suas extremidades horizontais ultrapassam o corpo.
Para a origem com margens maiores, o retângulo disponível inclui 40 unidades adicionais de espaço em cada lado. Com contain, sua escala é limitada por 80/140 em vez de 120/200. O emblema inalterado de 108 unidades de largura ocupa, portanto, cerca de 62 unidades do modelo. Esse número é calculado a partir das dimensões declaradas, não medido em pixels na captura.

Escolha o ajuste após revisar os limites da arte
Comece pela origem com margens reduzidas e contain quando o emblema completo importar. Mantenha margem suficiente na origem para qualquer traço ou efeito que precise continuar visível. Apertar demais uma viewport pode cortar arte legítima; não é uma instrução para remover toda margem.
Use cover quando o recorte das bordas for aceitável no design. No nosso exemplo ele esconde as pontas, portanto é uma escolha ruim se elas identificam o emblema. Um nó mais largo pode mudar a proporção do ajuste e revelar as pontas, mas também muda o layout do grafo. Ampliar as duas dimensões proporcionalmente mantém o mesmo recorte. Decida qual restrição você quer mudar.
Mantenha background-width e background-height em auto para esta comparação. Valores explícitos podem sobrescrever as dimensões de imagem usadas no ajuste. O padding do nó é outra entrada separada; a biblioteca documenta se o dimensionamento do fundo o inclui ou usa o corpo interno. Veja a referência de background-image antes de acrescentar esses controles. Nosso arquivo com preenchimento interno zero isola primeiro o espaço vazio da origem.
Para decisões de meet, slice e alinhamento no nível do SVG, continue no guia de preserveAspectRatio. Mudar o ajuste interno de um SVG e mudar o ajuste de fundo do Cytoscape são operações separadas.
Diagnostique o carregamento antes do recorte
Se o estado informar falha no carregamento, trocar contain por cover não é o próximo passo. Abra o recurso de imagem sozinho, confira a URL e as dimensões declaradas e reduza-o ao emblema independente composto só de caminho acima. Para uma URI de dados, codifique toda a string SVG em vez de concatenar marcação bruta ou um valor de cor sem escape.
Um SVG usado como imagem tem restrições diferentes de um SVG aberto como documento. O guia da MDN sobre SVG como imagem descreve restrições a scripts e recursos externos em contextos de imagem. Um arquivo de arte que depende de uma folha de estilos ou fonte externa precisa de um teste separado de entrega. Este exemplo evita essas dependências e coloca os rótulos do grafo fora do SVG.
Se a imagem carrega, examine o ajuste e o recorte do nó com uma forma claramente larga. Depois teste sua arte real no tamanho de nó e nos ambientes de navegador suportados pelo aplicativo. A documentação do Cytoscape menciona considerações SVG específicas de navegador; esta observação no Chrome não as resolve para Firefox ou todos os demais mecanismos.
Mantenha rótulos e arte editável separados
O exemplo usa label: 'data(label)' para rótulos do grafo e não contém texto SVG. Você pode mudar esse texto sem reconstruir o emblema. O caminho SVG permanece em seu original de origem, enquanto o grafo gerencia identidade, posição e relações dos nós.
O arquivo de teste examinado desenhou em superfícies Canvas. Ver um fundo SVG ali não transforma seus caminhos internos em elementos do grafo editáveis separadamente. Mantenha o original quando precisar mudar a abertura, a silhueta ou as cores. A exportação do grafo é um fluxo separado que exige a escolha de um exportador e teste próprio de entrega; este guia não promete que um grafo exportado preserve caminhos editáveis do emblema. O guia de arte no Graphviz explora a entrega por referência de imagem em outro renderizador de diagramas.
Se seu emblema personalizado existe só como PNG ou JPG, converta essa origem em arte vetorial, depois examine a silhueta, a abertura e os pequenos detalhes antes de definir os limites SVG. O PerfectVector pode ajudar a recuperar a geometria editável de origem. Estilos de fundo, rótulos dos nós e exportação do grafo continuam sendo etapas separadas. Um SVG adequado existente pode ir direto às verificações de ajuste.
Perguntas frequentes
Por que minha imagem SVG do nó é minúscula mesmo com cover? A imagem de origem pode conter muito espaço vazio na viewport ao redor do caminho. Compare uma cópia com limites mais próximos nas mesmas dimensões de nó antes de mudar o layout do grafo.
Devo usar contain ou cover para um emblema personalizado? Escolha contain quando o emblema completo importar. Escolha cover só quando o recorte observado nas bordas for aceitável no design e verifique com sua própria origem e forma de nó.
Um fundo SVG de nó cria caminhos editáveis no grafo? O arquivo Canvas testado usa o SVG como pintura de imagem. Mantenha o original da arte para editar caminhos; os contornos internos não são nós ou arestas separados do grafo neste exemplo.
Posso colocar rótulos no SVG? Este exemplo mantém rótulos nos dados do grafo e usa arte apenas de caminhos. Texto SVG, fontes e dependências de contexto de imagem precisam de verificações próprias de navegador e entrega.
Fontes
- Cytoscape.js — Imagem de fundo — estilo por URL de imagem, ajuste, sobrescrita de tamanho, referências de preenchimento interno e considerações SVG.
- Cytoscape.js — Lançamento v3.34.3 — versão fixada usada no arquivo de teste original.
- Cytoscape.js — Pacote de navegador v3.34.3 — implementação oficial com tag servida localmente para o teste de navegador.
- MDN — viewBox — retângulo de coordenadas de origem e mapeamento para viewport.
- MDN — encodeURIComponent — escape do componente SVG da URI de dados.
- MDN — naturalWidth — dimensões da imagem carregada, distintas dos limites do caminho.
- MDN — SVG como imagem — restrições do contexto de imagem e verificações de dependências.
Se seu emblema começa como raster, crie um original mestre SVG editável, examine os contornos e limites da origem e compare contain e cover no seu próprio layout de nós.
Mais do blog

Marcadores SVG Leaflet: alinhe a ponta com iconAnchor
Posicione marcadores SVG no Leaflet mapeando a ponta visível para iconAnchor. Considere margens do viewBox, ajuste de proporção e mudanças no tamanho do ícone.

Meça o comprimento de caminhos SVG sem confundir a escala
Meça caminhos SVG em unidades de usuário, considere transformações e tamanho nominal e diferencie totais de contornos, calibração pathLength e percurso de máquina.
