Command Palette

Search for a command to run...

Transformaciones en Canvas 2D: Traslación, Rotación, Escala y Sesgado

Aprende a aplicar transformaciones geométricas a elementos de Canvas usando translate(), rotate(), scale() y transform() para crear gráficos dinámicos y animaciones complejas.

Lectura: 14 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Las transformaciones se aplican al sistema de coordenadas, no a los objetos
  • translate() mueve el origen del sistema de coordenadas
  • rotate() rota el sistema de coordenadas alrededor del origen actual
  • scale() escala el sistema de coordenadas en los ejes X e Y
  • save() y restore() permiten guardar y restaurar el estado del contexto

Introducción a las Transformaciones

Las transformaciones en Canvas modifican el sistema de coordenadas en lugar de modificar directamente los objetos. Esto significa que cuando aplicas una transformación, todos los dibujos posteriores se ven afectados por esa transformación. Este enfoque es más flexible y permite crear efectos complejos combinando múltiples transformaciones.

Las transformaciones son acumulativas: cada transformación se aplica sobre el estado actual del sistema de coordenadas. Por ejemplo, si trasladas y luego rotas, la rotación se aplicará en la nueva posición traslada. Entender este orden es crucial para obtener los resultados esperados.

Transformaciones vs Modificar Coordenadas

Las transformaciones modifican el sistema de coordenadas, lo que es más eficiente que calcular manualmente las nuevas coordenadas para cada punto. También permite animaciones suaves donde las transformaciones cambian gradualmente sin redibujar todo el contenido.

Traslación (translate)

El método translate(x, y) mueve el origen del sistema de coordenadas a la posición especificada. Después de una traslación, todas las coordenadas que especifiques serán relativas al nuevo origen. Esto es útil para dibujar objetos en diferentes posiciones sin tener que calcular manualmente las coordenadas absolutas.

traslacion.js
Loading code...

Este ejemplo muestra cómo translate() mueve el origen del sistema de coordenadas. El primer rectángulo se dibuja en (0, 0) que ahora está en (50, 50) debido a la traslación. El segundo rectángulo se dibuja en (100, 100) que es relativo al nuevo origen, por lo que termina en (150, 150).

Usos comunes de translate()

Usa translate() para centrar el origen en el canvas (útil para rotaciones), para dibujar múltiples copias de un objeto en diferentes posiciones, o para simplificar las coordenadas de objetos complejos dibujándolos en (0, 0) y trasladándolos a la posición deseada.

Rotación (rotate)

El método rotate(angle) rota el sistema de coordenadas alrededor del origen actual. El ángulo se especifica en radianes, donde valores positivos rotan en sentido horario y valores negativos en sentido antihorario. Es importante notar que la rotación siempre ocurre alrededor del origen actual, no alrededor del centro del objeto que estás dibujando.

Para rotar un objeto alrededor de su propio centro, primero debes traslada el origen al centro del objeto, rotar, dibujar el objeto centrado en (0, 0), y luego restaurar el estado. Este patrón es fundamental para animaciones de rotación.

rotacion.js
Loading code...

Este ejemplo muestra cómo rotar un objeto alrededor de su centro. Primero trasladas el origen al centro del objeto, rotas, dibujas el objeto centrado en (0, 0), y finalmente restauras el estado. Este patrón es esencial para rotaciones correctas.

  • El ángulo se especifica en <strong>radianes</strong>, no grados
  • Rotación <strong>positiva</strong> = sentido horario
  • Rotación <strong>negativa</strong> = sentido antihorario
  • La rotación ocurre alrededor del <strong>origen actual</strong>
  • Para rotar un objeto, traslada al centro, rota, dibuja en (0,0), restaura

Error común: Rotar sin trasladar

Si rotas sin trasladar primero el origen al centro del objeto, el objeto rotará alrededor de la esquina (0, 0) del canvas, lo que probablemente no es lo que quieres. Siempre traslada al centro del objeto antes de rotar.

Escala (scale)

El método scale(x, y) escala el sistema de coordenadas en los ejes X e Y. Los valores mayores que 1 aumentan el tamaño, valores entre 0 y 1 disminuyen el tamaño, y valores negativos invierten el eje. Si solo especificas un valor, se aplica a ambos ejes.

La escala afecta todo: coordenadas, tamaños de formas, grosores de líneas, tamaños de fuente, etc. Esto significa que si escalas por 2, un rectángulo de 50x50 se dibujará como 100x100, y una línea de 2px de grosor se dibujará con 4px de grosor.

escala.js
Loading code...

Este ejemplo muestra diferentes escalas. El primer rectángulo está escalado por 2 (doble tamaño), el segundo por 0.5 (mitad de tamaño), y el tercero con escala negativa en X (invertido horizontalmente). Observa cómo la escala afecta también el grosor de las líneas.

Mejor práctica para escala

Para escalar un objeto sin afectar el grosor de las líneas, usa save() antes de escalar, escala, dibuja el objeto, y luego restore(). Si necesitas líneas con grosor constante independientemente de la escala, ajusta lineWidth dividiendo por el factor de escala.

Sesgado (transform)

El método transform(a, b, c, d, e, f) permite aplicar una matriz de transformación completa al sistema de coordenadas. Esta matriz incluye traslación, rotación, escala y sesgado (skew). Los parámetros a, b, c, d controlan rotación, escala y sesgado, mientras que e, f controlan la traslación.

El sesgado es útil para crear efectos de perspectiva o inclinación. Por ejemplo, para sesgar horizontalmente, puedes usar transform(1, 0, tan(angle), 1, 0, 0). Para sesgar verticalmente, usa transform(1, tan(angle), 0, 1, 0, 0). El ángulo se especifica en radianes.

sesgado.js
Loading code...

Este ejemplo muestra cómo crear efectos de sesgado. El primer rectángulo está sesgado horizontalmente, el segundo verticalmente, y el tercero combina ambos. Los efectos de sesgado son útiles para crear ilusiones de perspectiva o efectos estilísticos.

  • <strong>transform(a, b, c, d, e, f)</strong> - Matriz de transformación completa
  • <strong>a, d</strong> - Escala en X e Y
  • <strong>b, c</strong> - Sesgado (skew) en Y e X
  • <strong>e, f</strong> - Traslación en X e Y
  • Útil para efectos de <strong>perspectiva</strong> e inclinación

Guardar y Restaurar Estado

Los métodos save() y restore() permiten guardar y restaurar el estado del contexto de Canvas. El estado incluye todas las transformaciones actuales, estilos de dibujo (colores, grosores), y otras propiedades del contexto. save() empuja el estado actual en una pila, y restore() saca el estado más reciente de la pila.

Estos métodos son esenciales cuando necesitas aplicar transformaciones temporales. Por ejemplo, para dibujar un objeto rotado sin afectar los dibujos posteriores, usas save(), aplicas las transformaciones, dibujas el objeto, y luego restore() para volver al estado anterior.

guardar-restaurar.js
Loading code...

Este ejemplo muestra cómo save() y restore() permiten aplicar transformaciones temporales. Cada objeto se dibuja con sus propias transformaciones sin afectar a los demás, gracias a save() y restore(). Este patrón es fundamental para dibujar múltiples objetos con diferentes transformaciones.

Error común: Olvidar restore()

Si olvidas llamar a restore() después de save(), las transformaciones se acumularán y afectarán a todos los dibujos posteriores. Esto puede causar resultados inesperados difíciles de depurar. Siempre usa restore() después de save() para mantener el estado limpio.

Resumen: Transformaciones en Canvas

Conceptos principales:

  • Las transformaciones modifican el sistema de coordenadas, no los objetos
  • translate() mueve el origen del sistema de coordenadas
  • rotate() rota el sistema de coordenadas alrededor del origen actual
  • scale() escala el sistema de coordenadas en los ejes X e Y
  • transform() aplica una matriz de transformación completa

Mejores prácticas:

  • Usa save() y restore() para transformaciones temporales
  • Para rotar un objeto, traslada al centro, rota, dibuja en (0,0), restaura
  • Convierte grados a radianes multiplicando por Math.PI / 180
  • Ajusta lineWidth dividiendo por el factor de escala si necesitas grosor constante
  • Usa transform() para efectos de perspectiva y sesgado complejos