Transformaciones y Animaciones

Escalar, rotar y trasladar objetos.

Paso 1: Preparación del Canvas

Como siempre, asegúrate de tener tu elemento <canvas> definido en tu HTML:

				
					<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Transformaciones en Canvas</title>
</head>
<body>
    <canvas id="miCanvas" width="500" height="400" style="border:1px solid #000;"></canvas>
    <script src="script.js"></script>
</body>
</html>

				
			

Paso 2: Transformaciones en JavaScript

Veamos cómo realizar diferentes tipos de transformaciones en objetos dentro del canvas.

Trasladar (Translate)

Trasladar un objeto significa moverlo a una nueva posición en el canvas. Esto se hace modificando el sistema de coordenadas del contexto del canvas.

				
					var canvas = document.getElementById('miCanvas');
var ctx = canvas.getContext('2d');

// Trasladar el origen del contexto
ctx.translate(100, 100);

// Dibujar un rectángulo en las nuevas coordenadas
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 100, 50);  // El rectángulo aparecerá en (100, 100)

				
			

Rotar (Rotate)

Rotar implica girar el objeto alrededor del origen actual del sistema de coordenadas. Se especifica en radianes.

				
					// Rotar el contexto
ctx.rotate(Math.PI / 4);  // Rotar 45 grados

// Dibujar otro rectángulo que será rotado
ctx.fillStyle = 'blue';
ctx.fillRect(50, -25, 100, 50);

				
			

Escalar (Scale)

Escalar cambia el tamaño de los objetos dibujados en el canvas. Puedes especificar diferentes valores para escalar en el eje x y en el eje y.

				
					// Escalar el contexto
ctx.scale(0.5, 0.5);  // Reducir a la mitad en ambos ejes

// Dibujar un rectángulo escalado
ctx.fillStyle = 'green';
ctx.fillRect(200, 50, 100, 50);  // Las dimensiones serán la mitad de lo especificado

				
			

Consideraciones de Orden de Transformaciones

Es importante notar que el orden en que aplicas las transformaciones es crucial. Las transformaciones en canvas son acumulativas y afectan todas las operaciones de dibujo posteriores. Si necesitas aplicar una transformación solo a un objeto específico y luego volver al estado original, puedes usar ctx.save() y ctx.restore():

				
					ctx.save();  // Guardar el estado actual del contexto

// Aplicar transformaciones
ctx.translate(100, 100);
ctx.rotate(Math.PI / 4);
ctx.scale(0.5, 0.5);

// Dibujar un objeto transformado
ctx.fillStyle = 'purple';
ctx.fillRect(0, 0, 100, 50);

ctx.restore();  // Restaurar al estado guardado

// Dibujar otro objeto sin transformaciones
ctx.fillStyle = 'orange';
ctx.fillRect(0, 0, 50, 30);

				
			

Crear animaciones básicas.

Crear animaciones en HTML5 Canvas es un proceso interesante que combina varios conceptos que ya hemos visto, como la manipulación del contexto, el control de tiempos y las transformaciones. A continuación, te mostraré cómo crear una animación básica paso a paso.

Paso 1: Configuración Inicial del Canvas

Comencemos por establecer nuestro entorno básico en el archivo HTML:

				
					<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Animación Básica en Canvas</title>
</head>
<body>
    <canvas id="miCanvas" width="500" height="400" style="border:1px solid #000;"></canvas>
    <script src="script.js"></script>
</body>
</html>

				
			

Paso 2: Escribir el Script para la Animación

Vamos a crear un script para animar un objeto que se mueve a través del canvas. En este caso, haremos que un cuadrado se mueva de izquierda a derecha.

Preparar el Archivo JavaScript

En tu archivo script.js, vamos a establecer la lógica básica para nuestra animación.

				
					var canvas = document.getElementById('miCanvas');
var ctx = canvas.getContext('2d');

var posX = 0;  // Posición inicial del cuadrado en el eje X
var velX = 2;  // Velocidad de movimiento en píxeles por frame

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);  // Limpiar el canvas

    ctx.fillStyle = 'red';
    ctx.fillRect(posX, 100, 50, 50);  // Dibujar el cuadrado en la nueva posición

    posX += velX;  // Actualizar la posición para el siguiente frame

    if (posX > canvas.width || posX < 0) {
        velX = -velX;  // Cambiar la dirección cuando llegue al borde del canvas
    }

    requestAnimationFrame(draw);  // Llamar a draw para el siguiente frame
}

draw();  // Iniciar la animación

				
			

Explicación del Código

  1. Inicialización de Variables: Definimos la posición inicial (posX) y la velocidad (velX) del cuadrado.
  2. Función draw: Esta función realiza varias tareas:
    • Limpieza del Canvas: Usamos ctx.clearRect() para limpiar el canvas antes de dibujar un nuevo frame. Esto es crucial para no dejar rastros del cuadrado en sus posiciones anteriores.
    • Dibujar el Cuadrado: Usamos ctx.fillRect() para dibujar el cuadrado en su posición actualizada.
    • Actualizar Posición: Incrementamos posX por velX para mover el cuadrado.
    • Reversa de Dirección: Si el cuadrado alcanza el borde del canvas, invertimos su dirección modificando velX.
    • Animación Recursiva: requestAnimationFrame(draw) llama a la función draw nuevamente para crear un loop de animación. Esta función es preferida sobre setTimeout o setInterval porque es más eficiente y permite que el navegador controle la animación, pausándola si la pestaña no es visible.

Uso de requestAnimationFrame para animaciones eficientes.

¿Qué es requestAnimationFrame?

requestAnimationFrame es una función de JavaScript que le dice al navegador que quieres realizar una animación y solicita que el navegador programe la repintura de la ventana para el próximo ciclo de animación. El navegador intenta ejecutar estas llamadas a requestAnimationFrame antes del próximo repaint, generalmente a 60 veces por segundo, lo que equivale a 60 FPS (frames por segundo). Esto está en línea con la tasa de refresco estándar de la mayoría de los monitores de escritorio y garantiza que la animación sea suave.

Ventajas de requestAnimationFrame

  1. Eficiencia Energética: requestAnimationFrame es más eficiente en términos de energía en comparación con setTimeout o setInterval. Esto es porque requestAnimationFrame pausa las animaciones en pestañas que no están activas, reduciendo el uso de la CPU y conservando la batería en dispositivos móviles.
  2. Sincronización con el Navegador: Esta función está sincronizada con el refresco del navegador. Esto significa que maneja el ciclo de repintado del navegador, lo que ayuda a evitar problemas de tearing que pueden ocurrir cuando las actualizaciones de animación no están alineadas con los cambios en la pantalla.
  3. Sencillez y Control: Proporciona un mecanismo sencillo para las animaciones que requieren cuadros sucesivos, permitiendo un control más fino sobre la animación.

Cómo Usar requestAnimationFrame

Veamos cómo implementar una animación básica usando requestAnimationFrame. Supongamos que queremos animar un cuadrado que se mueve a lo largo del canvas:

				
					var canvas = document.getElementById('miCanvas');
var ctx = canvas.getContext('2d');

var posX = 0;  // Posición inicial del cuadrado
var velX = 2;  // Velocidad del cuadrado

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);  // Limpiar el canvas

    ctx.fillStyle = 'red';
    ctx.fillRect(posX, 100, 50, 50);  // Dibuja el cuadrado

    posX += velX;  // Actualiza la posición del cuadrado

    if (posX > canvas.width || posX < 0) {
        velX = -velX;  // Cambia la dirección al alcanzar los bordes
    }

    requestAnimationFrame(draw);  // Llama a draw para el siguiente cuadro
}

requestAnimationFrame(draw);  // Iniciar la animación

				
			

Ejemplo Explicado

  1. Inicialización: Establecemos la posición inicial y la velocidad del cuadrado.
  2. Función draw:
    • Limpia el canvas para preparar para el siguiente cuadro.
    • Dibuja el cuadrado en su nueva posición.
    • Actualiza la posición del cuadrado.
    • Revisa si el cuadrado ha llegado a los bordes del canvas para invertir su dirección.
    • Llama a requestAnimationFrame nuevamente para planificar el siguiente cuadro de la animación.
  3. Iniciar la Animación: La animación comienza llamando a requestAnimationFrame con draw como argumento.