1 puntos por GN⁺ 2024-03-09 | 1 comentarios | Compartir por WhatsApp

Trucos de animación con suavizado exponencial

  • Hay una técnica de animación simple que he usado casi siempre desde que empecé a trabajar en cosas relacionadas con animación.
  • Esta técnica se usa en muchos lugares: rotación y movimiento de cámara, movimiento de personajes en juegos por turnos, desplazamiento de elementos de UI, suavizado de cambios de volumen en bibliotecas de audio, entre otros.
  • La técnica no es nueva; puede que ya la hayas escuchado o usado, pero voy a explicar algunos ejemplos y el principio matemático detrás.

Botón de alternancia

  • Al crear un componente de UI, por ejemplo, supongamos que hacemos un botón de alternancia.
  • La posición del interruptor del botón se calcula según el estado: si está encendido, se establece en max_x; si está apagado, en min_x.
  • Este enfoque funciona bien, pero sin animación se ve algo sin vida.
  • La animación no solo añade atractivo visual, también ayuda a que el usuario entienda qué está ocurriendo.
  • En vez de mover el indicador del botón inmediatamente a su nueva posición, se cambia para que se desplace suavemente.
  • Ahora hay que actualizar la animación, pero esto tiene la desventaja de que parece moverse a velocidad constante.
  • Aquí se puede añadir una función de easing, por ejemplo 3t^2-2t^3 o una función como sqrt(t).
  • Las diferencias entre estas funciones de easing se notan mejor cuando la animación se reproduce lentamente.
  • Ahora, en lugar de actualizar la posición del interruptor, hay que rastrear el estado de la animación.
  • Al usar sqrt, hay que usar explícitamente funciones de easing distintas según la dirección de la animación.
  • Cuál se ve mejor depende del gusto, pero sqrt es el que se ve mejor. Hace que el interruptor empiece muy rápido, pero desacelere bien al acercarse a su destino.
  • La desventaja de esta versión es que requiere bastante manejo incluso en el caso más simple, y si el usuario hace clic a mitad de la animación aparece una discontinuidad con un salto repentino.

Movimiento de cámara

  • Supongamos una situación en la que el mapa y la cámara se desplazan o se mueven por el entorno.
  • También aquí conviene añadir animación.
  • Se presenta código que interpola a velocidad constante.
  • La vibración que aparece después de completar la animación ocurre porque target.x - position.x va alternando entre valores positivos y negativos.
  • En lugar de sign(delta), hace falta una función que limite el delta.
  • Este método es bastante complicado para algo sencillo.
  • Se ve raro cuando la velocidad de la animación es más rápida que la finalización de la animación.
  • También se podría ignorar la entrada del usuario mientras la animación está activa, pero eso produce una experiencia muy frustrante.
  • La solución perfecta es, por supuesto, el suavizado exponencial.
  • El código casi no cambia comparado con el ejemplo del botón de alternancia.

Cómo funciona por dentro

  • Se explica qué es 1 - exp(- speed * dt) y cómo funciona.
  • Empezando por la versión simple, se hace que la velocidad sea proporcional a la distancia entre la position actual y la nueva posición target, para que el movimiento sea más rápido.
  • Este método no necesita mantener ningún estado aparte de la posición actual y la posición objetivo, y se ajusta automáticamente aunque target cambie de golpe.
  • Pero hay un pequeño problema: si speed * dt es mayor que 1, la posición se pasa del objetivo.
  • Para resolver esto, se puede limitar el valor a 1.
  • La razón por la que speed * dt es demasiado grande es que el valor de speed es demasiado alto o dt es demasiado grande.
  • Para animación, sería ideal que todo funcionara perfectamente al aplicar dt.

Ecuaciones diferenciales (oh, no)

  • Se presenta un enfoque de dos pasos para resolver el problema.
  • Que position += (target - position) * speed * dt funcione para valores pequeños de dt pero falle para valores grandes de dt es un problema típico de los métodos numéricos para resolver ecuaciones diferenciales.
  • Se analiza qué resuelve esta ecuación.
  • Se explica que position += (target - position) * (1 - exp(- speed * dt)) es la fórmula correcta para cualquier dt.

Elegir la velocidad

  • Normalmente se piensa en la animación en términos de duración.
  • Al usar la fórmula exponencial, técnicamente la animación nunca termina y se completa en un tiempo infinito.
  • Lo que significa el parámetro speed es que 1 / speed es el tiempo en el que position se acerca a target por un factor de e = 2.71828....

Suavizado exponencial

  • Si buscas "suavizado exponencial", puedes encontrar un artículo de Wikipedia que parece totalmente no relacionado, pero en realidad incluye una fórmula muy similar a la discutida en esta publicación.
  • Si se asume que dt siempre es el mismo y que target cambia en cada iteración, se indexan los valores por número de iteración para calcular algo como position[i] = (target[i] - position[i - 1]) * factor.

Título del último párrafo

  • Tuve la idea para esta publicación durante varios meses, y me alegra haberla terminado por fin.
  • Gracias por ver y leer el registro de desarrollo.

Opinión de GN⁺

  • Este artículo explica la técnica de suavizado exponencial, utilizada para hacer que las animaciones se vean más fluidas y naturales. Esta técnica contribuye a mejorar la experiencia de usuario y a aumentar la intuición de la interfaz.
  • El suavizado exponencial también puede ser útil para simular movimiento físico; por ejemplo, en desarrollo de juegos se puede usar para que el movimiento de personajes o de la cámara se vea más natural.
  • Esta técnica es especialmente efectiva cuando elementos de la interfaz de usuario atraviesan cambios de estado, ya que permite representar esos cambios visualmente de forma muy suave. Por ejemplo, puede hacer que el movimiento de sliders o interruptores se vea más fluido.
  • Desde una mirada crítica, el suavizado exponencial puede dificultar el control preciso de la velocidad y la duración de una animación. Esto puede ser una limitación cuando un diseñador quiere ajustar con precisión un efecto de animación específico.
  • Otras bibliotecas o frameworks de animación que ofrecen funciones similares incluyen GreenSock Animation Platform(GSAP) y anime.js, que proporcionan un control más detallado de las animaciones junto con varias funciones de easing.
  • Al adoptar la técnica de suavizado exponencial, hay que encontrar un equilibrio entre la naturalidad de la animación y la precisión del control. La ventaja de elegir esta técnica es la mejora de la experiencia de usuario; la desventaja es que puede ser difícil ajustar con precisión el timing de la animación.

1 comentarios

 
GN⁺ 2024-03-09
Opiniones de Hacker News
  • Resumen del primer comentario:

    • Se enfatiza que este método no es una simple curva de easing ni una función smoothstep(), sino un método sin estado (stateless) que maneja entradas diversas de forma consistente.
    • Si has usado transiciones de CSS, puedes entender el problema que resuelve esta técnica.
    • El suavizado exponencial (exponential smoothing) tiene el problema de que se acerca al destino pero nunca lo alcanza.
    • Al usar un método similar para el desplazamiento inercial (inertial scrolling), se menciona que fue útil añadir un término de fricción (falsa).
  • Resumen del segundo comentario:

    • Como desarrollador de juegos, prefiere tweens con easing y duración predefinida para la mayoría de las situaciones de UI.
    • Sin embargo, esta técnica es muy útil para suavizar movimientos continuos e impredecibles donde no hay un punto de inicio o final claramente definido.
    • El lerp exponencial (exponential lerp) es útil pero poco conocido, y en algunos juegos se usa una interpolación lineal menos precisa, lo que causa problemas de animación.
    • Por estas razones, agradece el artículo, ya que muchas veces es difícil acceder a este tipo de conocimiento específico.
  • Resumen del tercer comentario:

    • Expresa desacuerdo con la afirmación del autor de que la raíz cuadrada (sqrt) es mejor que una cúbica (cubic) para un interruptor de palanca.
    • Sostiene que una función cúbica es más adecuada si se considera cómo funciona un interruptor de palanca real.
    • Considera que el artículo muestra muy bien cómo la animación puede mejorar la experiencia de usuario.
  • Resumen del cuarto comentario:

    • Admira los trucos no lineales simples que añaden disfrute a la interacción en línea.
    • Menciona que esto juega un papel importante en la percepción del color y que las personas no siempre entienden la aceleración.
  • Resumen del quinto comentario:

    • Dice que le gustó el artículo y menciona que escribió la misma técnica hace casi 10 años con el nombre lazy-easy.
    • Comenta que todavía usa esta técnica cuando quiere animaciones suaves sin gestión de estado.
  • Resumen del sexto comentario:

    • Señala que los artículos sobre easing parecen ser algo que cada generación tiene que redescubrir.
    • Recuerda que los sitios web experimentales de Yugo Nakamura a finales de los 90 fueron de los primeros ejemplos en usar easing libremente para dar una sensación orgánica.
  • Resumen del séptimo comentario:

    • Propone la idea de un interruptor que se mueva lentamente mientras se mantiene el toque/clic y, al soltarlo, haga un ajuste rápido del resto del recorrido.
    • No está seguro de lo que esto implicaría desde el punto de vista de UX, pero cree que podría indicar el momento en que una configuración se aplica o se guarda.
  • Resumen del octavo comentario:

    • Considera que esta técnica es útil no solo para interruptores, sino para varios usos.
    • Menciona una demo relacionada con Flickity y señala que esta técnica no incluía varias optimizaciones necesarias para estar lista para producción.
    • Critica que en los comentarios la gente no leyó bien el artículo o se está perdiendo puntos importantes.
  • Resumen del noveno comentario:

    • Evalúa positivamente el artículo y menciona que la demo funciona bien en Chrome, pero que en Firefox la página se le congeló.
  • Resumen del décimo comentario:

    • Considera que las pequeñas animaciones cuentan mucho y representan la mejor forma de diseño emocional.