PerfectVector
Por Irene Kim

SVG.js: importa diseños, edita un trazado y exporta SVG

Importa marcado SVG de confianza en SVG.js, cambia el color de un trazado con nombre y compara exportaciones de raíz completa o solo hijos. Conserva la geometría y revisa los archivos.

11 min de lectura
En esta página

Para importar un diseño en SVG.js y editar una de sus partes, pasa marcado SVG de confianza a .svg(), busca el elemento previsto por el ID asignado en el origen y cambia su relleno. Exporta la raíz SVG completa del diseño para obtener un archivo independiente. Exportar solo los hijos produce un fragmento: necesita una raíz con las dimensiones y el viewBox previstos antes de entregarlo como documento.

Esta guía usa un rombo hueco original y un triángulo separado. El triángulo pasa de ocre a coral mientras el rombo conserva su relleno turquesa y su abertura. Probamos el ejemplo completo de abajo con SVG.js 3.2.6, fijado a la versión oficial 3.2.6. Estas observaciones corresponden a dos trazados sencillos creados por nosotros, no a todas las funciones que otro SVG pueda contener.

Decide si necesitas formas activas o una imagen

Una instrucción import de JavaScript que produce la URL de un recurso responde a una cuestión de carga. Por sí sola no coloca los trazados del archivo en el árbol SVG activo de tu editor. La documentación actual de importación y exportación de SVG.js describe cómo importar marcado y recuperar un elemento SVG exterior o sus hijos.

RepresentaciónQué permite seleccionar nuestro ejemploComprobación de entrega
Marcado de confianza importado en una raíz SVG activaEl trazado llamado accentInspeccionar la raíz editada y volver a abrir su exportación
SVG cargado mediante un elemento de imagenEl elemento de imagen completoInspeccionar los datos de imagen por separado
Marcado solo de hijosDos elementos path sin la raíz originalProporcionar una raíz, dimensiones y un viewBox elegidos deliberadamente

Un SVG dentro de una imagen sigue siendo contenido SVG. Sin embargo, en nuestro control de contenedor de imagen, el árbol SVG que lo contiene tiene un elemento de imagen y ningún trazado directo; buscar accent en ese árbol no encuentra nada. No accede al documento de la imagen incrustada. MDN describe el contexto de imagen SVG separado y sus restricciones. No deduzcas el modelo de edición a partir de un renderizado que parece nítido.

Para la decisión general de inserción, lee SVG inline frente a una imagen. Si prefieres el modelo de objetos canvas de Fabric, el tutorial de importación de Fabric.js cubre otro analizador y otra API de edición.

Edita un trazado con nombre y guarda cada representación

Guarda el código completo de abajo como starter.html en una carpeta vacía. Sírvelo mediante HTTP, por ejemplo con python3 -m http.server 8000, y abre http://localhost:8000/starter.html. El script carga el paquete de versión fija desde su CDN, así que esta plantilla necesita conexión de red.

La página muestra el diseño original, la copia activa editada y un control de contenedor de imagen. Sus enlaces descargan el maestro original, las raíces completas antes y después, el fragmento de texto solo con hijos, una copia con nueva raíz y el contenedor de imagen. El informe lee píxeles de imágenes SVG pintadas en un canvas; no exporta 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>
 

El marcado importado contiene una raíz anidada llamada original-artwork. El ejemplo selecciona esa raíz antes de exportar, por lo que la copia de entrega tiene su viewport original de 240 × 160 en lugar de depender de un contenedor padre sin relación. Después selecciona accent dentro de esa raíz. SVG.js documenta las referencias mediante selectores y los métodos de elementos; los nombres explícitos de partes evitan depender del orden de los trazados.

El código se limita deliberadamente a su propio marcado fijo. No es un sanitizador de archivos SVG cargados. Analizar o insertar una cadena arbitraria no establece que sea segura; la referencia de DOMParser de MDN distingue el análisis de los riesgos de insertar contenido no confiable. Diseña una política separada de validación y confianza antes de adaptar esta rutina para archivos cargados.

Revisa el resultado guardado, no solo la vista previa activa

Nuestra ejecución real en el navegador produjo estas comprobaciones:

Representación guardadaTrazados en su árbol de documentoImágenesRelleno del triángulo
Maestro original20#d4a53a
Raíz completa antes de editar20#d4a53a
Raíz completa después de editar20#b95434
Hijos colocados en una raíz completa nueva20#b95434
Contenedor de imagen01Ocre original dentro de sus datos de imagen

Ambas cadenas d de los trazados originales siguieron idénticas en las exportaciones de antes y después. La muestra del interior del triángulo pasó de RGBA (212, 165, 58, 255) a (185, 84, 52, 255). El interior del rombo muestreado mantuvo (23, 107, 91, 255); su abertura y la esquina exterior siguieron con alfa 0. Los cinco archivos SVG independientes volvieron a abrirse como imágenes con dimensiones naturales de 240 × 160.

Cambia una parte con nombre
Comparación conceptual de diseños iguales de rombo hueco donde solo un triángulo separado cambia de dorado a coral
Ilustración conceptual de una edición de color por partes. Los límites decorativos y las flechas son referencias del diagrama; la plantilla ejecutada, el inventario del origen guardado y las comprobaciones de píxeles del navegador proporcionan las pruebas reales.

Esos resultados establecen la edición prevista para este archivo de prueba. No establecen preservación XML idéntica byte a byte, compatibilidad con todos los filtros o CSS ni idoneidad para un flujo de fabricación. La serialización de la biblioteca puede cambiar el marcado del documento manteniendo intactas estas cadenas de trazado concretas. Conserva el maestro original junto a la copia de entrega.

Para tu diseño, revisa las estructuras que uses realmente: nombres y grupos, recortes, degradados, transformaciones, trazos y texto. Vuelve a abrir el archivo exportado en su aplicación receptora y repite la edición prevista. La guía de edición SVG puede ayudar a diagnosticar la estructura de origen antes de cambiar el código de importación.

Trata la exportación solo de hijos como un fragmento deliberado

En esta ejecución, artwork.svg(false) devolvió dos trazados sin una etiqueta exterior svg. Omitió el viewport de la raíz del diseño. La raíz SVG separada rewrapped proporciona dimensiones de 240 × 160 y el mismo viewBox antes de aceptar esos hijos; su archivo exportado renderiza después el triángulo coral comprobado.

Elige entre un documento completo y un fragmento según el destino. Para una descarga independiente, conserva toda la raíz prevista. Para insertarlo en un dibujo existente, decide qué sistema de coordenadas padre, estilos heredados y definiciones usarán esos hijos. Este archivo sencillo no tiene recursos externos ni definiciones compartidas, así que no prueba si un fragmento con referencias lleva todas las dependencias que necesita.

Nuestra exportación del contenedor de imagen conservó un SVG codificado cuyos bytes decodificados coincidían con el maestro original. Ese control muestra una diferencia de representación, no una conversión ráster. Si tu origen ya es geometría vectorial utilizable, corrige la selección de elementos o el límite de exportación antes de volver a calcarlo.

Cuando el origen no tiene trazados que editar

Si tu ilustración plana PNG o JPG necesita regiones que se puedan recolorear por separado, prepara un candidato SVG con PerfectVector. Inspecciona los contornos y las aberturas y asigna después los nombres de partes que necesite tu aplicación. La vectorización no sabe que una región debe llamarse accent ni garantiza que un documento importado encaje con el modelo de datos de tu editor.

Conserva un maestro SVG adecuado cuando esas formas ya existan. Usa la introducción a la vectorización para decidir si la preparación de ráster a vector debe ir antes de tu código.

Preguntas frecuentes

¿SVG.js puede importar una cadena SVG para editar? Sí. Esta plantilla importa su propio marcado de confianza en un contenedor SVG activo, selecciona un trazado creado y cambia su relleno. Los archivos arbitrarios cargados necesitan una política separada de confianza y validación; la API de marcado no es un sanitizador.

¿Por qué veo el diseño pero no encuentro su trazado accent? Comprueba si importaste marcado activo o colocaste una imagen. Nuestro control de contenedor de imagen muestra un diseño SVG, pero no expone ningún trazado accent directo en su árbol. Revisa también el padre seleccionado y los ID reales del origen.

¿Una exportación solo de hijos es un archivo SVG completo? No en este archivo de prueba. Contiene dos trazados sin el viewport SVG exterior. Usa la raíz completa prevista para un archivo independiente o proporciona explícitamente la raíz y el sistema de coordenadas de destino al insertar un fragmento.

¿Una edición correcta demuestra que la exportación conserva todas las funciones SVG? No. Comprobamos dos trazados sencillos, sus valores de relleno, los datos de trazado exactos y cinco archivos reabiertos. Prueba las funciones y la aplicación receptora concretas que necesite tu diseño y conserva el maestro original.

Fuentes

  1. SVG.js — Importación y exportación, versión 3.2 — Importación de marcado y serialización de raíz completa frente a solo hijos.
  2. SVG.js — Referenciar y crear elementos, versión 3.2 — Búsqueda de elementos con nombre y cambio de sus propiedades.
  3. SVG.js — Versión 3.2.6 — Versión oficial fijada por la plantilla ejecutada.
  4. MDN — SVG como imagen — Contexto de inserción de imágenes y sus restricciones.
  5. MDN — DOMParser.parseFromString — Análisis de marcado y tratamiento separado de entradas no confiables.

Si tu ilustración solo existe como píxeles ráster y necesita ediciones por partes, prepara un candidato vectorial a partir de tu diseño. Revisa el contorno y las aberturas, conserva el maestro y comprueba después la edición con nombre y el SVG guardado en tu flujo receptor.

Más del blog

PerfectVector

Empieza con un SVG más limpio
y fácil de editar

Sin tarjeta de crédito