SVG.js: importe arte, edite um caminho e exporte SVG
Importe marcação SVG confiável no SVG.js, recolora um caminho nomeado e compare exportações da raiz completa e só dos filhos. Confira a geometria e os arquivos.
Nesta página
Para importar uma arte no SVG.js e editar uma parte, passe uma marcação SVG confiável para .svg(), encontre o elemento desejado pelo ID definido na criação e altere seu preenchimento. Exporte a raiz SVG completa da arte para obter um arquivo independente. Uma exportação apenas dos filhos é um fragmento: ela precisa de uma raiz com as dimensões e o viewBox pretendidos antes de ser entregue como documento.
Este guia usa um losango vazado original e um triângulo separado. O triângulo muda de ocre para coral, enquanto o losango mantém o preenchimento verde-azulado e a abertura. Testamos o exemplo completo abaixo com SVG.js 3.2.6, fixado na versão oficial 3.2.6. Essas observações dizem respeito a dois caminhos simples criados para o exemplo, e não a todos os recursos que outro SVG possa conter.
Decida se precisa de formas editáveis ou de uma imagem
Uma instrução de importação JavaScript que produz a URL de um recurso resolve uma questão de carregamento. Por si só, ela não coloca os caminhos do arquivo na árvore SVG ativa do seu editor. A documentação atual de importação e exportação do SVG.js descreve como importar marcação e recuperar um elemento SVG externo ou seus filhos.
| Representação | O que nosso exemplo permite acessar | Verificação da entrega |
|---|---|---|
| Marcação confiável importada para uma raiz SVG ativa | O caminho chamado accent | Inspecione a raiz editada e reabra sua exportação |
| SVG carregado por um elemento de imagem | O elemento de imagem inteiro | Inspecione o conteúdo da imagem separadamente |
| Marcação apenas dos filhos | Dois elementos de caminho sem a raiz original | Forneça uma raiz definida, dimensões e viewBox |
O SVG dentro de uma imagem continua sendo conteúdo SVG. Porém, no nosso controle com imagem encapsulada, a árvore SVG que o contém tem um elemento de imagem e nenhum caminho direto; procurar accent nessa árvore não encontra nada. A busca não entra no documento da imagem incorporada. A MDN descreve o contexto separado do SVG como imagem e suas restrições. Uma renderização nítida não revela o modelo de edição.
Para uma decisão mais ampla sobre incorporação, leia SVG inline versus imagem. Se você prefere o modelo de objetos de canvas do Fabric, o guia de importação do Fabric.js aborda outro analisador e outra API de edição.
Edite um caminho nomeado e salve cada representação
Salve o código completo abaixo como starter.html em uma pasta vazia. Sirva-o por HTTP, por exemplo com python3 -m http.server 8000, e abra http://localhost:8000/starter.html. O script carrega o pacote fixado pela CDN, portanto este exemplo exige conexão de rede.
A página exibe a arte original, a cópia editada ativa e um controle com a imagem encapsulada. Seus links baixam o arquivo mestre original, as raízes completas antes e depois, o fragmento de texto apenas com os filhos, uma cópia recolocada em uma raiz e o contêiner de imagem. O relatório lê pixels de imagens SVG desenhadas em um canvas; ele não exporta um PNG.
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Original SVG.js artwork import and export</title>
<style>
body { margin: 24px; font: 16px system-ui; background: #f6f2e8; }
main { display: grid; grid-template-columns: repeat(3, 260px); gap: 20px; }
figure { margin: 0; }
svg, img { display: block; background: white; border: 1px solid #bbb; }
pre { white-space: pre-wrap; font-size: 12px; }
</style>
<h1>Trusted artwork, one fill edit and two export forms</h1>
<main>
<figure><img id="original" alt="Original artwork"><figcaption>Original SVG image</figcaption></figure>
<figure><div id="live"></div><figcaption>Imported live SVG, accent edited</figcaption></figure>
<figure><div id="wrapper"></div><figcaption>Image wrapper, original artwork</figcaption></figure>
</main>
<p id="downloads"></p>
<pre id="report"></pre>
<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.2.6/dist/svg.min.js"></script>
<script>
const markup = '<svg xmlns="http://www.w3.org/2000/svg" id="original-artwork" width="240" height="160" viewBox="0 0 240 160">'
+ '<path id="body" d="M80 20 L140 80 L80 140 L20 80 Z M80 56 L104 80 L80 104 L56 80 Z" fill="#176b5b" fill-rule="evenodd"/>'
+ '<path id="accent" d="M172 48 L220 80 L172 112 Z" fill="#d4a53a"/></svg>';
const url = text => 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(text);
async function pixels(text) {
const image = new Image();
image.src = url(text);
await image.decode();
const canvas = document.createElement('canvas');
canvas.width = 240;
canvas.height = 160;
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
const rgba = (x, y) => [...ctx.getImageData(x, y, 1, 1).data];
return { naturalWidth: image.naturalWidth, naturalHeight: image.naturalHeight,
opening: rgba(80, 80), body: rgba(80, 40), accent: rgba(188, 80), corner: rgba(0, 0) };
}
function inventory(text) {
const node = new DOMParser().parseFromString(text, 'image/svg+xml').documentElement;
return { root: node.localName, viewBox: node.getAttribute('viewBox'),
paths: [...node.querySelectorAll('path')].map(p => ({ id: p.id, d: p.getAttribute('d'), fill: p.getAttribute('fill') })),
imageCount: node.querySelectorAll('image').length };
}
async function run() {
document.getElementById('original').src = url(markup);
const host = SVG().addTo('#live').size(240, 160).viewbox(0, 0, 240, 160);
host.svg(markup);
const artwork = host.findOne('#original-artwork');
const before = artwork.svg();
const accent = artwork.findOne('#accent');
const beforeD = accent.attr('d');
accent.fill('#b95434');
const full = artwork.svg();
const children = artwork.svg(false);
const rewrapped = SVG().size(240, 160).viewbox(0, 0, 240, 160);
rewrapped.svg(children);
const wrappedFull = rewrapped.svg();
const imageWrapper = SVG().addTo('#wrapper').size(240, 160).viewbox(0, 0, 240, 160);
imageWrapper.image(url(markup)).size(240, 160);
const wrapperFull = imageWrapper.svg();
const files = { 'master.svg': markup, 'before.svg': before, 'edited.svg': full,
'children-only.txt': children, 'rewrapped.svg': wrappedFull, 'image-wrapper.svg': wrapperFull };
for (const [name, text] of Object.entries(files)) {
const a = document.createElement('a');
a.href = name.endsWith('.txt') ? 'data:text/plain;charset=utf-8,' + encodeURIComponent(text) : url(text);
a.download = name;
a.textContent = name;
a.style.marginRight = '12px';
document.getElementById('downloads').append(a);
}
const results = {};
for (const [name, text] of Object.entries(files)) {
if (name.endsWith('.svg')) results[name] = { inventory: inventory(text), pixels: await pixels(text) };
}
document.getElementById('report').textContent = JSON.stringify({
requestedPackageVersion: '3.2.6',
scriptURL: document.querySelector('script[src]').src,
selectedAccentFound: Boolean(accent), selectedAccentDUnchanged: beforeD === accent.attr('d'),
allPathDUnchanged: JSON.stringify(inventory(before).paths.map(p => p.d)) === JSON.stringify(inventory(full).paths.map(p => p.d)),
childrenHasOuterSVG: /<svg[\s>]/i.test(children),
wrapperDirectPathCount: imageWrapper.find('path').length,
wrapperAccentFound: Boolean(imageWrapper.findOne('#accent')), results
}, null, 2);
}
run();
</script>
</html>
A marcação importada contém uma raiz aninhada chamada original-artwork. O exemplo seleciona essa raiz antes de exportar, de modo que a cópia de entrega tenha a área de visualização original de 240 × 160, sem depender de um contêiner pai sem relação com ela. Depois, seleciona accent dentro dessa raiz. O SVG.js documenta referências por seletores e métodos de elementos; nomes explícitos para as partes evitam depender da ordem dos caminhos.
O código é intencionalmente limitado à sua própria marcação fixa. Ele não é um sanitizador de uploads SVG. Analisar ou inserir uma string arbitrária não demonstra que ela é segura; a referência de DOMParser da MDN distingue a análise dos riscos de inserir conteúdo não confiável. Defina uma política separada de validação e confiança antes de adaptar esta função para uploads.
Inspecione o arquivo salvo, além da prévia ativa
Nossa execução real no navegador produziu estas verificações:
| Representação salva | Caminhos na árvore do documento | Imagens | Preenchimento do triângulo |
|---|---|---|---|
| Mestre original | 2 | 0 | #d4a53a |
| Raiz completa antes da edição | 2 | 0 | #d4a53a |
| Raiz completa depois da edição | 2 | 0 | #b95434 |
| Filhos inseridos em uma nova raiz completa | 2 | 0 | #b95434 |
| Contêiner de imagem | 0 | 1 | Ocre original no conteúdo da imagem |
As duas strings d dos caminhos originais permaneceram idênticas nas exportações antes e depois. O ponto amostrado no interior do triângulo mudou de RGBA (212, 165, 58, 255) para (185, 84, 52, 255). O ponto amostrado no interior do losango permaneceu em (23, 107, 91, 255); a abertura e o canto externo mantiveram alfa 0. Os cinco arquivos SVG independentes reabriram como imagens com dimensões naturais de 240 × 160.

Esses resultados comprovam a edição pretendida neste conjunto de teste. Não comprovam preservação do XML byte a byte, suporte a todos os filtros ou CSS, nem adequação a um fluxo de fabricação. A serialização da biblioteca pode alterar a marcação do documento e manter intactas estas strings específicas de caminhos. Guarde o mestre original junto à cópia de entrega.
Para sua própria arte, verifique as estruturas que realmente usa: nomes e grupos, recortes, gradientes, transformações, traços e texto. Reabra o arquivo exportado no aplicativo de destino e repita a edição pretendida. O guia de edição de SVG pode ajudar a diagnosticar a estrutura da origem antes de você mudar o código de importação.
Trate a exportação só dos filhos como um fragmento planejado
Nesta execução, artwork.svg(false) retornou dois caminhos sem a tag externa svg. O resultado omitiu a área de visualização da raiz da arte. A raiz SVG separada rewrapped fornece dimensões de 240 × 160 e o mesmo viewBox antes de receber os filhos; seu arquivo exportado então renderiza o triângulo coral verificado.
Escolha entre documento completo e fragmento conforme o destino. Para um download independente, mantenha a raiz completa pretendida. Para inserir em um desenho existente, decida qual sistema de coordenadas pai, quais estilos herdados e quais definições esses filhos usarão. Este exemplo simples não tem recursos externos nem definições compartilhadas, portanto não testa se um fragmento com referências carrega todas as dependências necessárias.
Nossa exportação do contêiner de imagem manteve um SVG codificado cujos bytes decodificados correspondiam ao mestre original. Esse controle mostra uma diferença de representação, não uma conversão raster. Se a origem já tem geometria vetorial utilizável, corrija a seleção do elemento ou o limite da exportação antes de vetorizar novamente.
Quando a origem não tem caminhos para editar
Se sua ilustração plana PNG ou JPG precisa de regiões que possam ser recoloridas separadamente, prepare um SVG candidato com PerfectVector. Inspecione os contornos e as aberturas, depois defina os nomes das partes que seu aplicativo precisa. A vetorização não sabe que uma região deve se chamar accent, nem garante que o documento importado se adapte ao modelo de dados do editor.
Mantenha um mestre SVG adequado quando essas formas já existirem. Use a visão geral da vetorização para decidir se a preparação raster para vetor deve sequer vir antes do seu código.
Perguntas frequentes
O SVG.js pode importar uma string SVG para edição? Sim. Este exemplo importa sua própria marcação confiável para um contêiner SVG ativo, seleciona um caminho criado com nome e altera seu preenchimento. Uploads arbitrários precisam de uma política separada de confiança e validação; a API de marcação não é um sanitizador.
Por que consigo ver a arte, mas não encontro o caminho accent? Confira se importou marcação ativa ou inseriu uma imagem. Nosso controle com imagem encapsulada mostra a arte SVG, mas não expõe nenhum caminho accent direto na árvore do contêiner. Confira também o pai selecionado e os IDs reais na origem.
Uma exportação apenas dos filhos é um arquivo SVG completo? Neste exemplo, não. Ela contém dois caminhos sem a área de visualização SVG externa. Use a raiz completa pretendida para um arquivo independente ou forneça explicitamente a raiz e o sistema de coordenadas de destino ao inserir um fragmento.
Uma edição bem-sucedida prova que a exportação preserva todos os recursos SVG? Não. Verificamos dois caminhos simples, seus valores de preenchimento, os dados exatos dos caminhos e cinco arquivos reabertos. Teste os recursos específicos e o aplicativo de destino de que sua arte precisa, e mantenha o mestre original.
Fontes
- SVG.js — Importação / exportação, versão 3.2 — Importação de marcação e serialização da raiz completa ou apenas dos filhos.
- SVG.js — Referências / criação de elementos, versão 3.2 — Localização de elementos nomeados e alteração de suas propriedades.
- SVG.js — Versão 3.2.6 — A versão oficial fixada no exemplo executado.
- MDN — SVG como imagem — Contexto de incorporação como imagem e suas restrições.
- MDN — DOMParser.parseFromString — Análise de marcação e tratamento separado de entradas não confiáveis.
Se sua ilustração existe apenas como pixels raster e precisa de edições por parte, prepare um vetor candidato com sua própria arte. Confira o contorno e as aberturas, guarde o mestre e comprove a edição pelo nome e o SVG salvo no seu fluxo de destino.
Mais do blog

Ícones SVG no MapLibre: pixels e tamanho do símbolo
Decodifique arte SVG para uma camada de símbolos MapLibre, controle densidade e tamanho do ícone e mantenha um original editável. Verifique a forma e a abertura exibidas.

Transformação de padrão SVG: gire a pintura, não a forma
Gire ou desloque pintura SVG repetida dentro de um emblema fixo com patternTransform. Compare a rotação do objeto inteiro e verifique origem, geometria e pixels.
