PerfectVector
Por Irene Kim9 min de leitura

Importar SVG no Fabric.js: arte editável no canvas

Importe SVG no Fabric.js como objetos editáveis, altere a cor de uma parte e exporte uma cópia SVG verificada. Siga um exemplo testado e separe problemas do arquivo original de erros de API.

Nesta página

Para importar SVG editável no Fabric.js, aguarde loadSVGFromString() ou loadSVGFromURL() e adicione os objetos retornados a um canvas. Mantenha uma referência à parte que você quer editar, altere seu preenchimento e exporte com canvas.toSVG(). Carregar a arte como imagem fornece outro modelo de edição: selecionar essa imagem não expõe cada região colorida como uma forma separada.

Essa distinção importa para um configurador de produtos, editor de emblemas ou ícone recolorível. Você precisa de objetos que correspondam às partes que o usuário pode mudar. Um arquivo com extensão .svg não garante essa estrutura.

Este passo a passo usa Fabric.js 7.4.0 e uma pequena luminária feita manualmente. Ele testa três formas durante importação, recoloração e exportação. É um exemplo original de teste de código, não uma conversão do PerfectVector nem uma afirmação de que todos os recursos de SVG passam pelo mesmo processo sem mudanças.

Escolha o modelo de objetos antes do carregador

O Fabric.js interpreta SVG em seus próprios objetos de canvas. Você edita esses objetos pela API do Fabric; eles não são elementos DOM SVG ativos dentro do canvas. A referência atual de loadSVGFromString documenta uma promessa que é resolvida com o resultado da interpretação e uma função reviver que recebe cada elemento de origem e seu objeto criado.

Sua tarefaPonto de partida útilConfira antes de continuar
Alterar formas separadasInterpretar SVG em objetos FabricA região de destino existe como objeto próprio
Mover a arte como uma unidadeAgrupar deliberadamente os objetos interpretadosEdições de filhos e seleção funcionam como pretendido
Inserir uma ilustração sem editar suas partesUsar um fluxo de imagemUma única imagem selecionável é suficiente
Recolorir uma arte disponível apenas como PNG ou JPGPreparar primeiro a geometria vetorialAs regiões vetorizadas correspondem às edições necessárias

Não deduza a estrutura de objetos pela aparência. Duas cores podem pertencer a traçados separados, enquanto várias ilhas desconectadas podem pertencer a um único traçado. O guia de desagrupamento SVG explica esse diagnóstico do arquivo de origem.

Execute um pequeno exemplo de importação, recoloração e exportação

Comece em uma pasta vazia. Instale a dependência com versão fixada:

npm install --save-exact fabric@7.4.0

Salve isto como index.html:

<!doctype html>
<html lang="en">
<meta charset="utf-8">
<title>Fabric SVG import test</title>
<canvas id="editor" width="320" height="240"></canvas>
<button id="recolor">Recolor shade</button>
<button id="export">Export SVG</button>
<div id="output"></div>
<pre id="report"></pre>
<script type="module" src="main.js"></script>
</html>

Salve isto como main.js. O caminho relativo do módulo permite que este pequeno exemplo seja executado sem empacotador. Em um aplicativo empacotado, importe os mesmos nomes de fabric.

import { Canvas, loadSVGFromString } from './node_modules/fabric/dist/index.min.mjs';
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="320" height="240" viewBox="0 0 320 240">
  <path id="shade" fill="#e6a23c" d="M115 40 H205 L230 135 H90 Z"/>
  <rect id="stem" x="151" y="135" width="18" height="57" fill="#214c54"/>
  <path id="base" fill="#214c54" d="M110 192 H210 L220 210 H100 Z"/>
</svg>`;
const canvas = new Canvas('editor', { width: 320, height: 240 });
const parts = new Map();
const parsed = await loadSVGFromString(svg, (element, object) => {
  const id = element.getAttribute('id');
  if (id) parts.set(id, object);
});
canvas.add(...parsed.objects.filter(Boolean));
canvas.requestRenderAll();
function report(exported) {
  const xml = new DOMParser().parseFromString(exported, 'image/svg+xml');
  const data = {
    version: '7.4.0',
    importedObjects: canvas.getObjects().length,
    types: canvas.getObjects().map(object => object.type),
    shadeFill: parts.get('shade').fill,
    exportedPaths: xml.querySelectorAll('path').length,
    exportedRects: xml.querySelectorAll('rect').length,
    exportedImages: xml.querySelectorAll('image').length,
  };
  document.querySelector('#report').textContent = JSON.stringify(data, null, 2);
  document.querySelector('#output').innerHTML = exported;
}
document.querySelector('#recolor').onclick = () => {
  parts.get('shade').set('fill', '#397e86');
  canvas.requestRenderAll();
  document.querySelector('#report').textContent = 'Shade recolored. Export to check delivery SVG.';
};
document.querySelector('#export').onclick = () => report(canvas.toSVG());
report(canvas.toSVG());

Sirva a pasta por HTTP, em vez de abrir o arquivo HTML diretamente. Por exemplo, se Python estiver instalado, execute python3 -m http.server 8000 e abra http://localhost:8000. Clique em Recolor shade e depois em Export SVG. O botão renderiza a string exportada abaixo do canvas; ele não baixa um arquivo.

Esta demonstração insere na prévia apenas a exportação de seu próprio exemplo fixo. Não reutilize essa prévia por innerHTML como manipulador geral de upload para SVG não confiável. O exemplo também omite tratamento de erros e validação de arquivos no nível do aplicativo.

O mapa captura os IDs do SVG original durante a interpretação. A recoloração acessa a cúpula por essa referência explícita, em vez de supor que o primeiro objeto retornado sempre é a parte desejada. Em um editor de produção, decida como esses identificadores e referências são armazenados ao salvar e reabrir um documento.

O que o teste mostrou

Nosso exemplo foi importado como três objetos: path, rect e path. Depois que a cúpula mudou de #e6a23c para #397e86, a prévia exportada mostrou a cúpula com a nova cor, enquanto a haste e a base mantiveram seu preenchimento escuro original. A exportação continha dois traçados, um retângulo e nenhum elemento de imagem.

Demonstração local real do Fabric.js mostrando a luminária recolorida no canvas, uma prévia SVG exportada correspondente e um relatório de três objetos importados com zero imagens exportadas
Captura autêntica do exemplo feito manualmente no Fabric.js 7.4.0 após recoloração e exportação. Essas observações se aplicam às três formas simples testadas aqui.

Essas verificações demonstram que este exemplo continua sendo geometria vetorial após a exportação. Elas não demonstram preservação do XML original, agrupamento, regras CSS ou de todos os recursos usados por outro arquivo. Mantenha o mestre original e compare uma cópia de entrega no aplicativo que a receberá.

Evite misturar tutoriais de callback com a API de promessas

Exemplos mais antigos costumam chamar fabric.loadSVGFromString(svg, callback) e esperar que esse callback receba todo o array de objetos. Esse não é o papel do segundo argumento na API atual: ele é uma função reviver por objeto. Aguarde o resultado da interpretação para obter a coleção completa.

O guia de migração para 6.0 do Fabric explica a mudança para importações nomeadas e APIs baseadas em promessas. Confira a versão instalada do pacote antes de adaptar um trecho antigo; substituir apenas a declaração de importação deixa errada a lógica de carregamento.

Para um arquivo SVG da mesma origem, o ponto de partida equivalente é:

import { loadSVGFromURL } from 'fabric';
const parsed = await loadSVGFromURL('/artwork.svg');
canvas.add(...parsed.objects.filter(Boolean));
canvas.requestRenderAll();

A documentação de loadSVGFromURL observa que ele busca o SVG e deve obedecer à política de mesma origem. Se o servidor remoto não permite sua origem, alterar o código de agrupamento não corrige a falha de rede. Teste primeiro um arquivo servido pelo seu próprio aplicativo e inspecione a requisição que falhou e a configuração CORS do servidor remoto.

Confira a editabilidade separadamente da aparência

Uma renderização bem-sucedida responde a uma pergunta: algo apareceu? Um editor precisa de mais verificações.

  1. Selecione a região que deve mudar. Confirme que outra parte não muda junto.
  2. Altere a cor pelo método set do objeto e solicite uma renderização, como faz o exemplo.
  3. Exporte e abra o resultado de forma independente. A API Canvas.toSVG do Fabric gera marcação SVG a partir do estado do canvas.
  4. Inspecione tudo de que sua arte real depende, como contornos, recortes, gradientes, texto ou transformações aninhadas. O exemplo simples acima não testa esses recursos.
  5. Salve, reabra e repita a edição pretendida no seu próprio editor antes de considerar o fluxo concluído.

Se a importação produz um objeto de imagem, examine o arquivo original em busca de um raster incorporado. O guia de conteúdo raster dentro de SVG mostra por que um invólucro SVG não dá aos pixels traçados editáveis. Se o arquivo original já tem formas vetoriais utilizáveis, trabalhe na importação e organização dos objetos, em vez de vetorizá-lo novamente.

Quando a arte raster precisa de uma conversão anterior

Se sua única imagem original é um PNG ou JPG de imagem plana e os usuários precisam editar suas regiões coloridas, o fluxo de imagem para vetor do PerfectVector pode ajudar a preparar uma versão candidata em SVG. Compare o resultado com o original, inspecione os traçados e confira se as regiões necessárias são editáveis de maneira independente antes de importá-lo no Fabric.js.

A vetorização não atribui significado específico do aplicativo, como cúpula, haste ou base. Os nomes do nosso exemplo foram definidos deliberadamente. Adicione seu próprio mapeamento de partes e regras de edição após inspecionar a geometria convertida. Para um conjunto reutilizável de ícones, o fluxo de PNG para SVG para kits de interface aborda preparação da imagem original e verificações de consistência.

Mantenha fotografias como raster quando elas devem continuar sendo fotografias. Mantenha um SVG original adequado quando ele já contém as formas necessárias. A visão geral de vetorização pode ajudar a decidir se a vetorização pertence ao fluxo.

Perguntas frequentes

O Fabric.js importa SVG como traçados editáveis? Ele pode interpretar conteúdo SVG compatível em objetos Fabric. A editabilidade depende da estrutura de origem: um traçado, um grupo de formas e um raster incorporado não oferecem as mesmas opções de edição. Inspecione os objetos retornados e teste a mudança específica de que você precisa.

Por que um exemplo antigo de loadSVGFromString falha? Tutoriais antigos podem esperar um callback de conclusão como segundo argumento. A API atual retorna uma promessa e usa esse argumento como reviver por objeto. Ajuste o código à versão instalada e aguarde o resultado da interpretação.

toSVG preserva exatamente o arquivo original? Não espere um documento de origem idêntico. Ele gera SVG a partir do estado do canvas Fabric. Preserve o mestre original e verifique a aparência exportada e as estruturas necessárias ao fluxo de destino.

Importar um PNG pode tornar suas regiões individuais editáveis? Inserir um PNG não o vetoriza em regiões vetoriais separadas. Se essas edições são necessárias, prepare primeiro geometria vetorial adequada, inspecione as partes resultantes e defina seus papéis no aplicativo.

Fontes

  1. Fabric.js — loadSVGFromString — Valor de retorno como promessa e contrato da função reviver de elemento de origem e objeto.
  2. Fabric.js — atualização para Fabric.js 6.0 — Importações nomeadas e migração de callbacks para promessas.
  3. Fabric.js — loadSVGFromURL — Interpretação de URL e restrições de busca de mesma origem.
  4. Fabric.js — API Canvas — Exportação do estado do canvas para marcação SVG.

Se a parte que falta é geometria editável de uma arte raster, prepare uma versão candidata em SVG com o PerfectVector. Confira primeiro as formas e prove que seu editor Fabric.js consegue recolorir a parte pretendida e exportar o resultado corretamente.

Mais do blog

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