SVGLoader de Three.js: convierte arte plano en una malla 3D
Carga trazados SVG en Three.js, conserva una abertura real, corrige la orientación vertical y dimensiona una malla extruida con un ejemplo pequeño y reproducible en el navegador.
En esta página
- Empieza por las formas a las que darás profundidad
- Carga el SVG y renderiza la malla
- Establece la orientación antes de medir y centrar
- Confirma el hueco antes de decorar
- Añade efectos de profundidad solo cuando funcione la extrusión simple
- Separa las comprobaciones de origen y destino
- Preguntas frecuentes
- Fuentes
Para convertir arte SVG plano en una malla Three.js, carga el SVG, convierte sus trazados en formas y pásalas a ExtrudeGeometry. Comprueba huecos, orientación vertical y dimensiones antes de añadir efectos. Una silueta reconocible puede tener una contraforma rellena o una esquina invertida.
Este tutorial usa una insignia original escrita manualmente en SVG con una abertura cuadrada y una esquina superior derecha recortada. La asimetría permite ver un error de orientación. Es un ejemplo geométrico de navegador, no una conversión de PerfectVector ni una prueba de fabricación.
Empieza por las formas a las que darás profundidad
Usa un SVG pequeño con contornos cerrados y rellenos para el primer intento. Guarda como badge.svg:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 180">
<path fill="#e64b35" fill-rule="evenodd"
d="M20 20H160L220 80V160H20Z M65 60H115V110H65Z"/>
</svg>Hay dos subtrazados cerrados en un elemento: un límite exterior y un cuadrado interior. La regla evenodd convierte la zona interior en una abertura. Un rectángulo blanco separado solo cubriría la cara en una imagen plana; no describiría la misma zona vacía.
La ilustración ocupa 200 por 140 unidades dentro de un viewBox de 240 por 180. Tenlo presente al dimensionar. Los márgenes vacíos pertenecen a la ventana SVG, no a la silueta extruida.
Si tienes un vector editable original, úsalo. Si solo tienes PNG o JPG, el proceso de imagen a vector de PerfectVector puede ayudarte a preparar trazados SVG. Inspecciona la vista previa y los contornos descargados, especialmente espacios negativos, antes de cargar en Three.js. Vectorizar aporta la ilustración 2D; el código siguiente aporta profundidad, materiales, iluminación y posición.
Carga el SVG y renderiza la malla
El ejemplo se probó con Three.js 0.186.0. Mantén biblioteca principal y complemento en la misma versión. En un proyecto de navegador con importaciones de paquetes, instala three@0.186.0, sirve los archivos por HTTP y crea un contenedor:
<div id="viewer"></div>
<script type="module" src="./main.js"></script>La herramienta de compilación debe resolver las importaciones three. Para una página sencilla sin ella, coloca este mapa antes del script de módulo usando archivos del mismo paquete instalado:
<script type="importmap">
{
"imports": {
"three": "./node_modules/three/build/three.module.js",
"three/addons/": "./node_modules/three/examples/jsm/"
}
}
</script>Coloca badge.svg junto al HTML. La URL relativa siguiente se resuelve respecto a esa página. Guarda esto como main.js:
import * as THREE from 'three';
import { SVGLoader } from 'three/addons/loaders/SVGLoader.js';
const data = await new SVGLoader().loadAsync('./badge.svg');
const artwork = new THREE.Group();
for (const path of data.paths) {
if (path.userData.style.fill === 'none') continue;
for (const shape of path.toShapes()) {
const geometry = new THREE.ExtrudeGeometry(shape, {
depth: 20, bevelEnabled: false, steps: 1
});
const material = new THREE.MeshStandardMaterial({
color: path.color, roughness: 0.65, metalness: 0
});
artwork.add(new THREE.Mesh(geometry, material));
}
}
if (!artwork.children.length) throw new Error('No filled shapes found');
// SVG y grows down; this scene uses y up.
artwork.scale.y = -1;
const bounds = new THREE.Box3().setFromObject(artwork);
const size = bounds.getSize(new THREE.Vector3());
const center = bounds.getCenter(new THREE.Vector3());
const scale = 4 / size.x;
artwork.scale.multiplyScalar(scale);
artwork.position.copy(center).multiplyScalar(-scale);
const scene = new THREE.Scene();
scene.background = new THREE.Color('#f1f3f5');
scene.add(artwork);
scene.add(new THREE.HemisphereLight(0xffffff, 0x596477, 2));
const light = new THREE.DirectionalLight(0xffffff, 3);
light.position.set(-3, 5, 7);
scene.add(light);
const camera = new THREE.PerspectiveCamera(35, 800 / 600, 0.1, 100);
camera.position.set(4, 3, 9);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(800, 600);
document.querySelector('#viewer').append(renderer.domElement);
renderer.render(scene, camera);SVGLoader es un complemento importado por separado. loadAsync() lee el archivo; parse(svgText) sirve si ya tienes el marcado como cadena.
En r186, usa path.toShapes(). Los ejemplos antiguos suelen llamar SVGLoader.createShapes(path). Se declaró obsoleto en r185 y delega en toShapes() en la versión probada. Comprueba tu versión antes de mezclar fragmentos de tutoriales.
El bucle omite deliberadamente fill="none". Maneja los rellenos sólidos del ejemplo; no es un renderizador SVG completo. Degradados, máscaras, imágenes incrustadas, trazos, opacidad y capas de color superpuestas necesitan decisiones propias en vez de asumir que la apariencia plana se volverá geometría 3D idéntica.

Establece la orientación antes de medir y centrar
Las coordenadas verticales SVG aumentan hacia abajo. Esta escena observa la ilustración con y positiva hacia arriba, así que artwork.scale.y = -1 restaura la orientación prevista. Compruébalo con la esquina recortada: debe estar arriba a la derecha.
El cambio de signo pertenece a esta configuración. No añadas otra inversión porque la malla siga pareciendo incorrecta tras girar una cámara u objeto padre. Compara primero un rasgo asimétrico conocido del original con la escena.
Las líneas siguientes miden el grupo invertido, calculan escala uniforme y desplazan su centro escalado al origen. Box3.setFromObject() mide límites incluidos hijos y transformaciones. Aquí el grupo no tiene padre transformado ni rotación al medirse.
La extrusión original mide 200 por 140 por 20. Establecer ancho 4 da escala 4 / 200, o 0.02. Como se aplica a los tres ejes, los límites resultan 4 por 2.8 por 0.4. Profundidad 20 en el constructor no sigue siendo 20 después de escalar el grupo.
Son unidades de escena. No se afirma que una unidad sea un milímetro. Si necesitas interpretación física concreta, defínela explícitamente y valídala mediante el proceso de destino.
Confirma el hueco antes de decorar
La prueba produjo un trazado cargado, una forma y un hueco. También lanzamos un rayo por la abertura cuadrada y otro por la zona sólida: la abertura no devolvió impacto y la zona sólida sí. Rayos por la esquina superior derecha recortada y la inferior derecha sólida confirmaron la orientación independientemente de la vista inclinada.
Puedes empezar por una comprobación visual más sencilla: mira la cara de frente y después en ángulo contra un fondo de contraste. La abertura debe mostrar el fondo y sus paredes laterales aparecer al mover la cámara. Una cara blanca cubriendo el área es otro resultado.
Si una contraforma se rellena, aísla esa forma. Inspecciona si el original usa subtrazados, objetos rellenos separados, recorte o máscara. No ocultes el problema con color de material. La guía de huecos SVG que se rellenan explica las diferencias; el diagnóstico de extrusión cubre reparación de contornos cuando el original está roto.
Añade efectos de profundidad solo cuando funcione la extrusión simple
El ejemplo desactiva biseles para inspeccionar fácilmente las dimensiones iniciales. Las opciones de ExtrudeGeometry controlan por separado profundidad, tamaño y grosor de bisel y muestreo de curvas. Revisa huecos pequeños y límites al activar biselado. Un borde decorativo cambia la geometría que acabas de medir.
Para curvas, inspecciona la silueta al tamaño y distancia de cámara de tu aplicación. Aumenta el muestreo solo si las facetas lo necesitan; reducir nodos innecesarios del original es una tarea aparte. Ningún ajuste restaura detalle ausente.
Un dibujo solo de trazos también requiere otra decisión. El cargador expone pointsToStroke() para geometría de trazos, pero el bucle de formas rellenas los omite. Si la línea visible debe ser una cinta extruida, decide primero qué contorno cerrado la define. Si debe seguir siendo una línea en escena, crea una representación de línea o trazo.
En React, ejecuta carga y renderizado exclusivos de navegador en el cliente y libera geometría, materiales y renderizador propios al quitar la vista. El ejemplo compacto renderiza una vez con tamaño fijo; un visor de producción necesita gestionar cambios de tamaño y su ciclo de recursos.
Separa las comprobaciones de origen y destino
Una malla de navegador sirve para insignia interactiva, vista previa de logotipo o decoración de escena. No demuestra que sea una pieza estanca y dimensionalmente adecuada. Si el destino es fabricación, usa el proceso de imagen a SVG para impresión 3D e inspecciona ahí el modelo importado.
Para pantalla, separa tres archivos o etapas: SVG editable, malla derivada y presentación de escena. Facilita distinguir si el fallo viene de geometría de trazados, construcción de malla o cámara e iluminación. Otras guías de procesos SVG explican cómo reparar el original antes de cargarlo.
Preguntas frecuentes
¿Por qué mi SVG está al revés en Three.js? Las coordenadas verticales SVG aumentan hacia abajo. En una escena con y positiva hacia arriba y vista frontal, invertir la escala y del grupo puede restaurar la orientación. Comprueba un rasgo asimétrico antes de añadir otra inversión o rotación.
¿Debo usar createShapes o toShapes? Este ejemplo usa path.toShapes() con Three.js 0.186.0. SVGLoader.createShapes() quedó obsoleto en r185. Usa la API de tu versión instalada, con paquete principal y complemento de la misma versión.
¿Convierte SVGLoader un PNG dentro de SVG en malla? Una imagen rasterizada incrustada no proporciona los contornos rellenos del ejemplo. Obtén primero trazados adecuados o usa la imagen como textura si lo que buscas es conservar su apariencia.
¿La extrusión conserva el ancho de trazo SVG? Este ejemplo extruye formas rellenas y omite trazados sin relleno. La geometría de trazo necesita otro proceso; una línea pintada gruesa no es automáticamente el contorno cerrado de una cinta extruida.
Fuentes
- Three.js — SVGLoader — Importación del complemento, métodos de análisis y carga, ayuda de trazos y obsolescencia de createShapes.
- Three.js — ShapePath — Convertir colecciones de trazados en formas con toShapes.
- Three.js — ExtrudeGeometry — Extrusión, profundidad, bisel y muestreo de curvas.
- Three.js — Box3 — Medir límites de objetos transformados y obtener tamaño y centro.
¿Partes de un emblema solo rasterizado? Prepara un candidato SVG, inspecciona contornos rellenos y aberturas y pruébalo en esta escena pequeña antes de crear el visor completo.
Más del blog

Importar SVG en Unreal Engine: comprueba la geometría de Motion Design
Prepara un SVG para Motion Design de Unreal Engine, revisa huecos y piezas separadas y distingue la geometría de escena de las texturas o imágenes de interfaz en ejecución.

Importar SVG en Rhino: elige curvas, sombreados o superficies
Elige la opción adecuada para importar SVG en Rhino 8, comprueba los tipos de objeto y los huecos y decide cuándo hay que trazar un logotipo raster antes de modelarlo.