En este artículo vamos a explicar cómo voltear o reflejar una imagen en un lienzo Canvas con HTML5 y JavaScript, tanto en horizontal como en vertical. Cuando desarrollamos un videojuego o una animación con HTML5 Canvas, es habitual que necesitemos que un personaje, enemigo u otro elemento gráfico mire hacia el lado contrario. Por ejemplo, si nuestro personaje camina hacia la izquierda, queremos que su imagen también se oriente en esa dirección, como si se diera la vuelta. A este efecto se le conoce como voltear, reflejar o espejar una imagen.
Hay que tener en cuenta que, aunque en los navegadores modernos esta técnica es rápida, no es gratuita. Si estás dibujando decenas o cientos de imágenes o sprites volteados en cada frame del videojuego, aplicar transformaciones para reflejarlos puede ralentizar el renderizado, especialmente en dispositivos con poca potencia. En estos casos, se recomienda utilizar imágenes o sprites ya prediseñados con las orientaciones necesarias.
Sin embargo, la técnica de voltear una imagen o sprite en Canvas con JavaScript puede ser muy útil cuando hay pocos elementos en pantalla. Por ejemplo, en el caso de un jefe final que de repente se “desdobla” o aparece una copia reflejada de sí mismo. Veamos una función en JavaScript que permite lograr este efecto en un lienzo HTML5 Canvas.
Función JavaScript para voltear una imagen
Esta función asume que tenemos la variable general (ctx) para trabajar sobre un lienzo canvas y le pasamos como parámetro un objeto (imagen) el cual contiene todas las propiedades necesarias para dibujar imagenes en un lienzo canvas, al estilo de una imagen independiente como en nuestro videojuego vanilla JavaScript.
function drawFlipped(imagen) {
ctx.save();
const flipX = (imagen.flipX) ? -1 : 1;
const flipY = (imagen.flipY) ? -1 : 1;
const dx = (imagen.flipX) ? -imagen.x - imagen.width : imagen.x;
const dy = (imagen.flipY) ? -imagen.y - imagen.height : imagen.y;
ctx.scale(flipX, flipY);
ctx.drawImage(
imagen.img,
imagen.sx, imagen.sy, imagen.sw, imagen.sh,
dx, dy, imagen.width, imagen.height
);
ctx.restore();
}
Código JavaScript para voltear una imagen
El flujo de nuestra función JavaScript para voltear una imagen funciona de la siguiente manera:
- Guardamos el estado del Canvas.
- Comprobamos si hay que voltear en alguno de los ejes (X, Y).
- Ajustamos las coordenadas de dibujo (dx, dy) para que la esquina de la imagen invertida quede en el mismo lugar que la imagen original.
- Escalamos el contexto en (X, Y) para invertir los ejes si procede.
- Dibujamos la imagen volteada y posicionada segun procede.
- Restauramos el estado original del Canvas para seguir dibujando normalmente.
Con esta función JavaScript, podemos voltear cualquier imagen tanto en horizontal, vertical o simultáneamente y todo queda perfectamente alineado. Veamos que realiza cada instrucción en detalle.
ctx.save();
Antes de hacer cualquier transformación en el Canvas, guardamos el estado actual del contexto de dibujo con esta instrucción. Esto nos permite hacer cambios en las herramientas de dibujo del Canvas y devolver su estado sin afectar al resto de dibujos.
const flipX, flipY;
Obtenemos las propiedades de la imagen (imagen.flipX
, imagen.flipY
) que pueden ser true
(queremos voltear en horizontal/vertical) o false
. Si se omite esta propiedad en (imagen) simplemente se interpreta como false. Cuando es true
, flipX
vale -1, lo que significa que queremos inveertir el eje (X). Si es false
o no existe, flipX
vale 1
, lo que significa que dejamos el eje (X) igual.
Para la constante (flipY
) operamos exactamente igual, pero para el eje vertical (Y). Con -1 se invierte el eje vertical y con 1 mantiene la orientación normal.
const dx, dy;
Una vez obtenidos los ejes (X, Y) que queremos voltear, debemos calcular las nuevas coordenadas (dx, dy) donde se dibujará la imagen. Sin no hay volteo, entonces en (dx) guardamos la esquina izquierda original. Si hay volteo, entonces debemos compensar la esquina izquierda original a modo de espejo:
-imagen.x
invierte la distancia al origen (0, 0).-imagen.width
desplaza la imagen para que su esquina izquierda invertida acabe en la posición correcta.
Para la constante (dy) operamos exactamente igual, pero para el eje vertical (Y). Si no hay volteo, entonces (dy) es igual a la imagen original, pero si hay volteo entonces obtenemos (-imagen.y - imagen.height
) para que el dibujo volteado “encaje” en la misma posición.
El concepto clave para entender esto es que al voltear una imagen, en realidad estamos invirtiendo los ejes del lienzo Canvas. De manera que si el Canvas empieza en (0, 0) en su esquina superior izquierda y los píxeles crecen hacia la derecha y abajo, al voltear los ejes esta orientación cambia. El origen (0, 0) sigue estando arriba a la izquierda, pero ahora los números crecen hacia la izquierda y hacia arriba.
ctx.scale(flipX, flipY);
Esta línea es la clave para voltear una imagen en Canvas con JavaScript. Al utilizar ctx.scale(x, y)
cambia tanto el tamaño como la orientación del sistema de coordenadas del canvas. Si pones un número negativo en alguno de los ejes (X, Y), hará que todo lo que se dibuje después en ese eje se dibuje al revés, como si fuera un espejo. Si mantenemos el 1
, significa que no cambiamos nada.
IMPORTANTE: Esto no cambia la imagen, solo cambia cómo se dibuja mientras esta transformación está activa. La orientación y el tamaño de la imagen original se mantienen intactos.
ctx.drawImage(…);
Esta instrucción del Canvas es la que realmente dibuja la imagen, pero hay un detalle importante: si te fijas en cómo se han escrito sus coordenadas, verás que usamos las variables (dx, dy)
para posicionarla correctamente en el lienzo. Estas variables compensan los cambios aplicados en los ejes (X, Y) al voltear la imagen, lo que nos permite colocarla exactamente en su misma posición original, tanto si ha sido reflejada como si no.
ctx.restore();
Una vez que hemos dibujado la imagen volteada, usamos ctx.restore();
para restaurar el lienzo Canvas a sus valores originales antes de voltear. Esto es importante porque si no lo hiciéramos, todo lo que dibujáramos después también se vería afectado.
Voltear una imagen con JavaScript
Voltear una imagen con JavaScript en Canvas puede parecer complicado, pero con esta función ahora puedes hacerlo fácilmente. Este sistema es muy útil para videojuegos, animaciones, y cualquier caso en el que necesites que un personaje mire hacia los cuatro costados a partir de una sola imagen.
Aunque el código JavaScript para voltear una imagen consume un poco más de procesamiento al renderizar la imagen, la diferencia es prácticamente imperceptible si lo usas solo para una o unas pocas imágenes. Incluso si tienes varias animaciones simultáneas, el rendimiento no se verá afectado mientras no estés dibujando varias docenas de imágenes volteadas por frame. Podemos resumir cuándo conviene usar esta función y cuándo es mejor recurrir a imágenes previamente volteadas con el siguiente esquema.
Cuándo voltear imágenes en JavaScript
Situación | ¿Vale la pena usar scale()? |
---|---|
Pocos objetos | ✅ Sí, no afecta mucho |
Muchos objetos por frame | ❌ Mejor usar imágenes volteadas |
Plataforma potente (PC) | ✅ Puedes usar scale() sin miedo |
Móviles o hardware limitado | ❌ Usa imágenes ya volteadas |
Necesitas efectos dinámicos | ✅ scale() es flexible |
Resumiendo, si una imagen o sprite se voltea frecuentemente (por ejemplo, personajes habituales que miran izquierda/derecha), carga las dos versiones prediseñadas. Si es algo ocasional o decorativo, puedes usar scale()
sin miedo.
¡ Espero que este artículo sea de vuestro interés !