Facilitar animaciones en Canvas
El canvas
elemento en HTML y Canvas API en JavaScript se combinan para formar una de las principales posibilidades de animación y gráficos rasterizados en la web. Un caso de uso común de Canvas es generar imágenes mediante programación para sitios web, en particular juegos. Eso es exactamente lo que hice en un sitio web que creé para jugar al Solitario. Las cartas, incluido todo su movimiento, están realizadas en lienzo.
En este artículo, veamos específicamente la animación en lienzo y las técnicas para hacer que se vean más suaves. Analizaremos específicamente cómo facilitar las transiciones, como “entrada y salida fácil”, que no son gratuitas en el lienzo como lo hacen en CSS.
Comenzamos con un lienzo estático. Dibujé en el lienzo una única carta que saqué del DOM:
Comenzamos con una animación básica: mover ese naipe en el lienzo. Incluso para cosas bastante básicas como requiere trabajar desde cero en el lienzo, tendremos que comenzar a desarrollar funciones que podamos usar.
Primero, crearemos funciones para ayudar a calcular las coordenadas X e Y:
function getX(params) { let distance = params.xTo - params.xFrom; let steps = params.frames; let progress = params.frame; return distance / steps * progress;}
function getY(params) { let distance = params.yTo - params.yFrom; let steps = params.frames; let progress = params.frame; return distance / steps * progress;}
Esto nos ayudará a actualizar los valores de posición a medida que la imagen se anima. Luego seguiremos renderizando el lienzo hasta que se complete la animación. Hacemos esto agregando el siguiente código a nuestro addImage()
método.
if (params.frame params.frames) { params.frame = params.frame + 1; window.requestAnimationFrame(drawCanvas); window.requestAnimationFrame(addImage.bind(null, params))}
¡Ahora tenemos animación! Estamos incrementando constantemente en 1 unidad cada vez, lo que llamamos animación lineal.
Puedes ver cómo la forma se mueve del punto A al punto B de forma lineal, manteniendo la misma velocidad constante entre los puntos. Es funcional, pero le falta realismo. El comienzo y el final son discordantes.
Lo que queremos es que el objeto acelere (acerque) y desacelere (alegue), de modo que imite lo que haría un objeto del mundo real cuando entre en juego cosas como la fricción y la gravedad.
Una función de facilitación de JavaScript
Lo lograremos con una transición “cúbica” de entrada y salida fácil. Hemos modificado una de las ecuaciones que se encuentran en las funciones de aceleración de Flash de Robert Penner para que sea adecuada para lo que queremos hacer aquí.
function getEase(currentProgress, start, distance, steps) { currentProgress /= steps/2; if (currentProgress 1) { return (distance/2)*(Math.pow(currentProgress, 3)) + start; } currentProgress -= 2; return distance/2*(Math.pow(currentProgress, 3)+ 2) + start;}
Al insertar esto en nuestro código, que es una facilidad cúbica , obtendremos un resultado mucho más fluido. Observe cómo la tarjeta acelera hacia el centro del espacio y luego disminuye la velocidad cuando llega al final.
Facilitación avanzada con JavaScript
Podemos obtener una aceleración más lenta con facilidad cuadrática o sinusoidal.
function getQuadraticEase(currentProgress, start, distance, steps) { currentProgress /= steps/2; if (currentProgress = 1) { return (distance/2)*currentProgress*currentProgress + start; } currentProgress--; return -1*(distance/2) * (currentProgress*(currentProgress-2) - 1) + start;}
function sineEaseInOut(currentProgress, start, distance, steps) { return -distance/2 * (Math.cos(Math.PI*currentProgress/steps) - 1) + start;};
Para una aceleración más rápida, utilice una facilidad quíntica o exponencial:
function getQuinticEase(currentProgress, start, distance, steps) { currentProgress /= steps/2; if (currentProgress 1) { return (distance/2)*(Math.pow(currentProgress, 5)) + start; } currentProgress -= 2; return distance/2*(Math.pow(currentProgress, 5) + 2) + start;}
function expEaseInOut(currentProgress, start, distance, steps) { currentProgress /= steps/2; if (currentProgress 1) return distance/2 * Math.pow( 2, 10 * (currentProgress - 1) ) + start; currentProgress--; return distance/2 * ( -Math.pow( 2, -10 * currentProgress) + 2 ) + start;};
Animaciones más sofisticadas con GSAP
Utilizar tus propias funciones de aceleración puede ser divertido, pero ¿qué pasa si quieres más potencia y flexibilidad? Podrías seguir escribiendo código personalizado o podrías considerar una biblioteca más potente. Para eso recurramos a la plataforma de animación GreenSock (GSAP).
La animación se vuelve mucho más fácil de implementar con GSAP. Tomemos este ejemplo, donde la tarjeta rebota al final. Tenga en cuenta que la biblioteca GSAP está incluida en la demostración.
La función clave es moveCard
:
function moveCard() { gsap.to(position, { duration: 2, ease: "bounce.out", x: position.xMax, y: position.yMax, onUpdate: function() { draw(); }, onComplete: function() { position.x = position.origX; position.y = position.origY; } });}
En el gsap.to
método es donde ocurre toda la magia. Durante los dos segundos que dura, el position
objeto se actualiza y, con cada actualización, se llama a onUpdate, lo que activa el lienzo que se volverá a dibujar.
Y no hablamos sólo de rebotes. Hay toneladas de diferentes opciones de flexibilización para elegir.
Poniendolo todo junto
¿Aún no estás seguro de qué estilo y método de animación deberías utilizar en el lienzo cuando se trata de suavizar? Aquí hay un lápiz que muestra diferentes animaciones de relajación, incluido lo que se ofrece en GSAP.
Echa un vistazo a mi juego de cartas Solitario para ver una demostración en vivo de las animaciones que no son GSAP. En este caso, he añadido animaciones para que las cartas del juego entren y salgan con facilidad cuando se mueven entre pilas.
Además de crear movimientos, las funciones de aceleración se pueden aplicar a cualquier otro atributo que tenga un estado desde y hasta, como cambios en opacidad, rotaciones y escala. Espero que encuentres muchas maneras de utilizar las funciones de aceleración para que tu aplicación o juego se vea más fluido.
Deja un comentario