SVG: Gráficos Vectoriales Escalables como XML Vivo
Scalable Vector Graphics (SVG) representa un cambio fundamental con respecto a los gráficos raster—cada forma, texto y efecto se define matemáticamente en lugar de estar mapeado en píxeles. Un archivo SVG es XML puro; se escala infinitamente sin pérdida, se anima de forma nativa en navegadores e se integra sin problemas con JavaScript y CSS. A diferencia de PDF o EPS (documentos vectoriales estáticos), SVG es interactivo, responsivo y vinculado a estándares web.
Estructura del Documento SVG: Espacio de Nombres XML y Elemento Raíz
Cada SVG comienza como XML con la declaración de espacio de nombres SVG:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100px" height="100px">
<!-- Todas las formas, texto, definiciones van aquí -->
</svg>
Atributos críticos:
xmlns: Espacio de nombres XML (siemprehttp://www.w3.org/2000/svg)viewBox="min-x min-y ancho alto": Define el sistema de coordenadas. UnviewBox="0 0 100 100"+width="200px" height="200px"escala el espacio lógico de 100×100 a píxeles físicos de 200×200—preservando relación de aspecto de forma predeterminadawidth/height: Dimensiones físicas (píxeles, em, cm, etc.). Omitir para ser 100% responsivopreserveAspectRatio: Controla comportamiento de estiramiento (por defectoxMidYMid meet= centrado, sin distorsión)
Primitivas de Forma: Rect, Circle, Ellipse, Line, Polygon
<rect x="10" y="10" width="50" height="30" fill="blue" stroke="black" stroke-width="2"/>
<circle cx="50" cy="50" r="20" fill="red"/>
<ellipse cx="100" cy="50" rx="30" ry="15" fill="green"/>
<line x1="0" y1="0" x2="100" y2="100" stroke="black" stroke-width="2"/>
<polygon points="50,10 90,90 10,90" fill="yellow"/>
Todas las primitivas soportan:
- Atributos de relleno:
fill="color",fill-opacity="0.5",fill-rule="evenodd"(lógica de relleno de trazado complejo) - Atributos de trazo:
stroke="color",stroke-width="2",stroke-linecap="round",stroke-linejoin="bevel" - Transformación:
transform="translate(10,20) rotate(45) scale(2)"(transformaciones encadenadas)
Elemento Path: Curvas Bézier y Formas Complejas
El elemento <path> utiliza la sintaxis de trazado SVG—una cadena de comandos de una sola letra:
<path d="M 10,10 L 90,10 Q 90,90 50,90 C 50,50 10,50 10,10 Z" fill="purple" stroke="black"/>
| Comando | Argumento | Significado |
|---|---|---|
| M/m | x,y | Mover a (absoluto M / relativo m) |
| L/l | x,y | Línea a |
| H/h | x | Línea horizontal a (vertical: V/v) |
| Q/q | cx,cy x,y | Bézier cuadrático (un punto de control) |
| C/c | cx1,cy1 cx2,cy2 x,y | Bézier cúbico (dos puntos de control) |
| A/a | rx,ry rotación-eje-x bandera-arco-grande bandera-barrido x,y | Arco (comando más complejo de SVG; dos radios de control, rotación, banderas de tamaño/dirección) |
| S/s | cx2,cy2 x,y | Cúbica suave (omitir primer punto de control—inferido del anterior) |
| T/t | x,y | Cuadrática suave |
| Z/z | — | Cerrar trazado (línea implícita al inicio) |
Ejemplo: Semicírculo vía Arco:
<path d="M 50,10 A 40,40 0 0,1 50,90" fill="none" stroke="blue" stroke-width="2"/>
(A 40,40 = radios x/y; 0 = sin rotación; 0,1 = arco pequeño, barrido en el sentido de las agujas del reloj; termina en 50,90)
Transformaciones: Manipulación del Espacio de Coordenadas
Las transformaciones se componen y se anidan; las transformaciones interiores se aplican antes que las exteriores:
<g transform="translate(50,50) rotate(45) scale(2)">
<rect width="10" height="10" fill="blue"/>
</g>
Resultado: Rectángulo dibujado en el origen (0,0) → scale(2) → rotate(45°) → translate(50,50).
Transformación de matriz (subyacente a todas las operaciones):
<g transform="matrix(a,b,c,d,e,f)"><!-- Aplica [a c e] [b d f] [0 0 1] --></g>
Rellenos y Trazos: Colores Sólidos, Gradientes, Patrones
Relleno sólido:
<circle cx="50" cy="50" r="30" fill="rgb(255,100,50)" opacity="0.7"/>
Gradiente lineal:
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:red;stop-opacity:1"/>
<stop offset="100%" style="stop-color:blue;stop-opacity:1"/>
</linearGradient>
</defs>
<rect width="100" height="100" fill="url(#grad1)"/>
Gradiente radial (centrado):
<radialGradient id="grad2" cx="50%" cy="50%" r="50%">
<stop offset="0%" style="stop-color:yellow"/>
<stop offset="100%" style="stop-color:orange"/>
</radialGradient>
Patrón (imagen en mosaico):
<pattern id="pat1" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse">
<rect width="10" height="10" fill="lightblue"/>
<circle cx="5" cy="5" r="3" fill="darkblue"/>
</pattern>
<rect width="100" height="100" fill="url(#pat1)"/>
Filtros: Desenfoque, Sombra, Morfología
Los filtros SVG son increíblemente poderosos para efectos sin mapas de bits:
<defs>
<filter id="shadow">
<feGaussianBlur in="SourceGraphic" stdDeviation="3"/>
<feOffset dx="2" dy="2" result="offsetblur"/>
<feFlood flood-color="black" flood-opacity="0.5" result="flood"/>
<feComposite in="flood" in2="offsetblur" operator="in" result="color"/>
<feComposite in="color" in2="SourceGraphic" operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
</filter>
</defs>
<circle cx="50" cy="50" r="30" fill="blue" filter="url(#shadow)"/>
Primitivos de filtro comunes:
feGaussianBlur: Desenfoque gaussiano (stdDeviation en píxeles)feOffset: Desplazar entrada (dx, dy)feFlood: Relleno de color sólidofeComposite: Combinar dos entradas (operador:in,out,atop,arithmetic, etc.)feMorphology: Erosión/dilatación de bordes (operador:erode/dilate)feColorMatrix: Ajustar matiz, saturación, brillofeBlend: Fusionar dos entradas (normal, multiply, screen, overlay, etc.)
Elemento Texto: Tipografía y Posicionamiento
<text x="10" y="20" font-family="Arial" font-size="16" fill="black">Hola SVG</text>
<text x="50" y="50" text-anchor="middle" dominant-baseline="middle">Texto Centrado</text>
<!-- Texto a lo largo de trazado -->
<path id="curve" d="M 10,10 Q 100,50 190,10" fill="none"/>
<text font-size="14">
<textPath href="#curve" startOffset="50%" text-anchor="middle">
El texto sigue la curva
</textPath>
</text>
Atributos:
x,y: Posición de anclajetext-anchor:start/middle/enddominant-baseline:auto/middle/hanging/alphabeticfont-size,font-family,font-weight,font-style
Animación: SMIL y CSS
SMIL (Synchronized Multimedia Integration Language):
<circle cx="50" cy="50" r="30" fill="blue">
<animate attributeName="cx" from="50" to="150" dur="2s" repeatCount="indefinite"/>
<animate attributeName="r" from="30" to="50" dur="2s" repeatCount="indefinite"/>
</circle>
animateTransform: Animar transformaciones (rotate, scale, translate, skew)animateMotion: Mover a lo largo del trazadoanimate: Interpolar cualquier atributo numérico
Animación CSS/JavaScript (enfoque moderno):
<style>
@keyframes spin { to { transform: rotate(360deg); } }
.spinner { animation: spin 2s linear infinite; }
</style>
<circle class="spinner" cx="50" cy="50" r="30" fill="blue"/>
Interactividad de JavaScript:
const circle = document.querySelector('circle');
circle.addEventListener('click', () => {
circle.setAttribute('fill', 'red');
});
SVG Responsivo: Media Queries y Escalado de Viewbox
<svg viewBox="0 0 100 100">
<style>
@media (max-width: 600px) {
.label { font-size: 8px; }
.shape { stroke-width: 1; }
}
@media (min-width: 601px) {
.label { font-size: 14px; }
.shape { stroke-width: 2; }
}
</style>
<rect class="shape" x="10" y="10" width="80" height="80"/>
<text class="label" x="50" y="50">Responsivo</text>
</svg>
El viewBox adapta el espacio de coordenadas lógico; las consultas de media CSS ajustan el renderizado según el tamaño de pantalla.
SVG vs PDF, EPS, JPEG, PNG, WEBP
| Aspecto | SVG | EPS | JPEG | PNG | WEBP | |
|---|---|---|---|---|---|---|
| Formato | Texto XML | Binario (basado en PostScript) | Texto PostScript | Binario raster | Binario raster | Binario raster |
| Vector/Raster | Vector (escala infinita) | Vector (escala infinita) | Vector (escala infinita) | Raster (resolución fija) | Raster (resolución fija) | Raster (resolución fija) |
| Tamaño de archivo | Pequeño (basado en texto) | Grande (fuentes incrustadas, imágenes) | Grande (gastos de PostScript) | Pequeño (con pérdidas) | Medio (sin pérdidas) | Pequeño (con pérdidas) |
| Soporte web | Nativo (DOM/CSS/JS) | Plugin requerido | Raramente se usa | Nativo | Nativo | Nativo |
| Animación | Nativa (SMIL/CSS) | Estática | Estática | N/A | N/A | N/A |
| Interactividad | Completa (JavaScript) | Limitada | Ninguna | Ninguna | Ninguna | Ninguna |
| Calificación de archivo | Buena (estándar ISO) | Excelente (estable) | Aceptable (obsoleta) | Aceptable (con pérdidas) | Buena (sin pérdidas) | Desconocida (edad del formato) |
| Calidad de impresión | Excelente (vectores) | Excelente | Excelente | Aceptable (pixelada) | Buena | Aceptable |
Procesamiento de SVG en Python
Lectura y modificación:
import xml.etree.ElementTree as ET
from lxml import etree
# Analizar SVG
tree = ET.parse('image.svg')
root = tree.getroot()
# Modificar color de relleno en todos los círculos
ns = {'svg': 'http://www.w3.org/2000/svg'}
for circle in root.findall('.//svg:circle', ns):
circle.set('fill', 'red')
# Guardar
tree.write('modificado.svg')
Usando biblioteca svgwrite:
import svgwrite
dwg = svgwrite.Drawing('salida.svg', size=('200px', '200px'))
dwg.add(dwg.circle(center=(100, 100), r=50, fill='blue'))
dwg.add(dwg.rect((10, 10), (50, 50), fill='green'))
dwg.save()
Conversión por lotes SVG → PNG (rasterización):
# Inkscape
inkscape entrada.svg --export-type=png --export-width=1024
# ImageMagick
convert -density 300 entrada.svg salida.png
# cairosvg (Python)
from cairosvg import svg2png
svg2png(url='entrada.svg', write_to='salida.png', dpi=300)
Cuándo Elegir SVG
- Logos, iconos, diagramas: Independiente de resolución; escala de favicon a cartelera
- Visualización de datos interactiva: D3.js, Plotly renderiza a SVG; vincula datos a interactividad
- Gráficos responsivos: Un único archivo se adapta a móvil, tableta, escritorio vía viewBox + media queries CSS
- Animación en navegadores: Animaciones SMIL y CSS se cargan instantáneamente; sin gastos de códec de vídeo
- Rendimiento web: Compresión basada en texto; gzip reduce en 50–70%
- Ilustración lista para impresión: Exportar desde Inkscape/Illustrator; escala a cualquier DPI
- Evitar SVG si: Imágenes fotorrealistas (rasterizar), conjuntos de datos masivos (10K+ trazados sobrecargan el renderizado), offline primero (requiere biblioteca SVG si no es nativo)
SVG es la base de los gráficos web modernos—verdadera escalabilidad encontrando interactividad y animación en un único formato portátil.
Conversiones relacionadas
Lo más habitual al trabajar con imágenes son estas direcciones de conversión: