PerfectVector
Por Irene Kim10 min de lectura

SVG con Path2D en canvas: reutiliza trazados al tamaño correcto

Reutiliza datos de trazado SVG en canvas con la transformación viewBox, colores, huecos y densidad de píxeles correctos. Sigue un ejemplo original y conserva el archivo maestro SVG editable.

En esta página

Pasa el atributo d de un trazado a new Path2D(d) y dibújalo con un contexto canvas. Para igualar el SVG, transfiere también su correspondencia de coordenadas, pintura y regla de relleno. El constructor acepta datos de trazado; no importa un documento SVG ni aplica su viewBox, CSS o transformaciones de grupo (constructor Path2D de MDN).

Esto importa cuando un icono personalizado se ve bien como SVG, pero aparece pequeño, desplazado, negro o con la abertura rellena en canvas. El ejemplo siguiente corrige esas diferencias con dos trazados y una transformación de ajuste explícita. Empieza por geometría vectorial existente cuando la tengas. La vectorización solo es útil cuando la ilustración que necesitas reutilizar sigue existiendo como píxeles.

Qué contiene un objeto Path2D

Piensa en los datos de trazado como la descripción de contornos. Otras instrucciones SVG están fuera de esa cadena, y tu código de dibujo canvas debe proporcionar las que necesite.

Entrada SVGResponsabilidad de canvas
Valor d de un trazadoConstruir la geometría Path2D
viewBox y tamaño mostradoCalcular la transformación de dibujo
fill y fill-ruleEstablecer fillStyle y pasar la regla a fill()
transform del padre o trazadoAplicar por separado la transformación equivalente
CSS, degradados, máscaras, texto e imágenesImplementar el renderizado necesario o elegir otro método

El ejemplo usa rellenos literales, dos trazados hijos directos y ninguna otra función SVG. Es deliberadamente lo bastante pequeño para inspeccionarlo. Copiar su bucle de extracción a un importador SVG arbitrario perdería estilos heredados y elementos incompatibles.

Compara el original con un canvas sin configurar

Este emblema original tiene un cuerpo redondeado verde azulado, una punta naranja y una abertura cuadrada. Su viewBox empieza en (20, 10), no en (0, 0). El subtrazado interior recorre la misma dirección que el límite exterior, por lo que importa la regla evenodd declarada.

Coloca este SVG y un canvas en una página HTML:

<svg id="source" xmlns="http://www.w3.org/2000/svg"
     viewBox="20 10 120 80" width="240" height="160">
  <path fill="#126d70" fill-rule="evenodd"
        d="M40 20 H90 Q110 20 110 40 V60 Q110 80 90 80 H40 Q30 80 30 70 V30 Q30 20 40 20 Z M50 35 H80 V60 H50 Z"/>
  <path fill="#f19b38" d="M115 25 L135 50 L115 75 Z"/>
</svg>
<canvas id="result"></canvas>

Si recorres los dos valores d y llamas a ctx.fill(new Path2D(d)) sin establecer nada más, la geometría usa coordenadas canvas y la pintura y regla de relleno predeterminadas. No adquiere automáticamente el aspecto del SVG. fill() de canvas acepta tanto un trazado como una regla explícita evenodd o nonzero; nonzero es el valor predeterminado (fill() de MDN).

Comparación de navegador de un emblema SVG, un renderizado Path2D sin configurar pequeño y negro con la abertura rellena y un renderizado canvas de dos colores correctamente ajustado
Los mismos trazados creados manualmente en un navegador: referencia SVG, Path2D sin configurar y ajuste explícito con pinturas y evenodd restaurados. La tabla registra dimensiones del mapa de bits para cuatro entradas de tamaño y DPR.

Método: renderizamos este SVG creado manualmente en el navegador, dibujamos sus dos trazados mediante ambos métodos canvas y volvimos a ejecutar el código publicado en una página HTML independiente. La captura es una salida real del navegador. Demuestra el tratamiento de coordenadas y pintura, no una conversión de PerfectVector.

Transforma el viewBox para ajustarlo al canvas

El comportamiento predeterminado de SVG que conserva proporciones ajusta el viewBox dentro del área visible y lo centra. La especificación de sistemas de coordenadas SVG define esa correspondencia. Para este ejemplo plano, reproduce xMidYMid meet con una escala uniforme y una traslación:

scale = min(cssWidth / viewBoxWidth, cssHeight / viewBoxHeight)
tx = (cssWidth - viewBoxWidth * scale) / 2 - viewBoxX * scale
ty = (cssHeight - viewBoxHeight * scale) / 2 - viewBoxY * scale

Los últimos términos eliminan el origen distinto de cero. A 240 × 160, la escala es 2, tx es -40 y ty es -20. A 300 × 120, la escala pasa a 1.5; el viewBox ajustado de 180 píxeles de anchura tiene 60 píxeles de espacio horizontal a cada lado. La traslación es, por tanto, (30, -15) después de tener en cuenta el origen.

Usa el siguiente script después del HTML anterior. Gestiona los atributos directos de trazado de este ejemplo, redibuja todo el canvas y separa el tamaño CSS del tamaño del mapa de bits:

const source = document.querySelector("#source");
const vb = source.viewBox.baseVal;
const layers = [...source.querySelectorAll("path")].map(el => ({
  path: new Path2D(el.getAttribute("d")),
  fill: el.getAttribute("fill"),
  rule: el.getAttribute("fill-rule") || "nonzero"
}));
 
function draw(canvas, cssWidth, cssHeight, dpr = window.devicePixelRatio || 1) {
  canvas.style.width = `${cssWidth}px`;
  canvas.style.height = `${cssHeight}px`;
  canvas.width = Math.round(cssWidth * dpr);
  canvas.height = Math.round(cssHeight * dpr);
  const ctx = canvas.getContext("2d");
  const scale = Math.min(cssWidth / vb.width, cssHeight / vb.height);
  const tx = (cssWidth - vb.width * scale) / 2 - vb.x * scale;
  const ty = (cssHeight - vb.height * scale) / 2 - vb.y * scale;
  const px = canvas.width / cssWidth;
  const py = canvas.height / cssHeight;
  ctx.setTransform(px * scale, 0, 0, py * scale, px * tx, py * ty);
  for (const layer of layers) {
    ctx.fillStyle = layer.fill;
    ctx.fill(layer.path, layer.rule);
  }
}
 
draw(document.querySelector("#result"), 240, 160);
 

Establecer canvas.width y canvas.height borra y reinicia el contexto. La función establece después la transformación completa y vuelve a pintar todas las capas, por lo que las llamadas repetidas no acumulan escala. Supone un viewBox válido con anchura y altura positivas y dimensiones solicitadas positivas.

px y py usan las dimensiones reales redondeadas del mapa de bits. Así las coordenadas CSS se corresponden con los píxeles asignados incluso cuando la densidad solicitada produce dimensiones fraccionarias. El ejemplo de devicePixelRatio de MDN explica por qué el tamaño de visualización canvas y las dimensiones en píxeles necesitan un tratamiento separado.

Comprueba por separado tamaño y densidad de píxeles

Pasamos valores DPR 1 y 2 explícitamente a la misma función con dos tamaños CSS. Son entradas controladas de densidad, no una afirmación de haber probado dos dispositivos físicos. La relación de píxeles del dispositivo informada por el navegador para la llamada predeterminada era 2.

Tamaño CSSArgumento DPRMapa de bits canvas observado
240 × 1601240 × 160
240 × 1602480 × 320
300 × 1201300 × 120
300 × 1202600 × 240

El centro de la abertura permaneció transparente en los cuatro casos. Una densidad mayor cambia la resolución del mapa de bits; no corrige una transformación equivocada ni recupera una regla de relleno ausente. Redibuja cuando cambien las dimensiones CSS previstas o la relación de píxeles del dispositivo. Una ampliación solo mediante CSS estira el mapa de bits que ya está en el canvas.

Si el original ya es incorrecto antes de llegar a canvas, usa las comprobaciones de tamaño SVG y viewBox. Si solo canvas es incorrecto, compara primero su transformación y tratamiento de pintura con la referencia SVG correcta.

Conserva el original y elige el método de importación adecuado

Conserva el archivo maestro SVG y sus atributos junto a los datos de trazado derivados. Una rutina de dibujo Path2D es útil cuando controlas un pequeño conjunto de contornos y sus estilos. Para un SVG complejo del que solo necesitas el aspecto renderizado por el navegador, cargarlo como imagen y dibujarla puede evitar reconstruir cada función. Ese método sigue pintando en el mapa de bits canvas.

Guardar la salida canvas como PNG crea una imagen rasterizada, aunque el dibujo empezara con trazados vectoriales. La API de exportación canvas produce un blob de imagen; la compatibilidad PNG es obligatoria (toBlob() de MDN). Conserva SVG para editar trazados después. Del mismo modo, un archivo SVG puede contener una imagen rasterizada en lugar de datos de trazado útiles; el diagnóstico de imágenes incrustadas ayuda a distinguir esos casos.

PerfectVector encaja cuando solo queda un PNG o JPG de tu icono personalizado y necesitas contornos reutilizables. Convierte esa imagen en SVG e inspecciona su silueta, colores separados y aberturas pequeñas antes de extraer trazados para canvas. Un archivo maestro SVG limpio debe pasar directamente al paso de preparación. La vectorización no implementa la correspondencia del viewBox, copia CSS ni hace editable como vectores un PNG de canvas.

Para una familia completa de iconos, establece la cuadrícula y las reglas de pintura compartidas del kit de interfaz antes de conectar cada rutina de dibujo. Hay más ejemplos de preparación SVG en el blog.

Antes de usar el dibujo en tu interfaz

  • Comprueba la referencia SVG con las mismas dimensiones de visualización que el canvas.
  • Confirma el origen del viewBox, además de su anchura y altura.
  • Transfiere las pinturas y la regla de relleno prevista; inspecciona cada abertura.
  • Ten en cuenta las transformaciones de grupo en lugar de copiar solo d.
  • Lee los valores reales de canvas.width y canvas.height y prueba el mayor tamaño de visualización previsto.
  • Conserva el archivo maestro SVG y proporciona un nombre accesible o texto circundante adecuado para la interfaz.

Preguntas frecuentes

¿Puede Path2D importar un archivo SVG completo? No. Su entrada de cadena son datos de trazado SVG, como el valor del atributo d de un trazado. La estructura del documento, la correspondencia del viewBox, los estilos y las transformaciones de grupo necesitan tratamiento separado.

¿Por qué se rellenó el hueco de mi SVG en canvas? Comprueba la regla de relleno y las direcciones de los subtrazados. Este ejemplo requiere evenodd, mientras que fill de canvas usa nonzero por defecto. Pasa la regla prevista al rellenar el objeto Path2D.

¿Dibujar trazados SVG en canvas conserva una exportación vectorial? Los trazados siguen siendo instrucciones de dibujo reutilizables en tu programa, pero exportar el canvas como PNG produce píxeles. Conserva el SVG original para editar y entregar como vector.

Fuentes

  1. MDN — constructor Path2D — Define la cadena de datos de trazado que acepta el constructor.
  2. W3C — sistemas de coordenadas SVG — Define el origen del viewBox, su correspondencia con el área visible y la alineación que conserva proporciones.
  3. MDN — fill() de canvas — Documenta el relleno de trazados y las reglas evenodd y nonzero.
  4. MDN — devicePixelRatio — Explica el tamaño de visualización CSS y la resolución del mapa de bits canvas.
  5. MDN — toBlob() de canvas — Documenta la exportación de imágenes rasterizadas desde canvas.

¿Solo tienes un icono rasterizado? Prepara su SVG con PerfectVector, comprueba el contorno y las aberturas y compara el dibujo canvas con ese SVG a los tamaños reales de tu interfaz.

Más del blog

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