Amazing Clock ⏰ Animación con Jetpack Compose (Parte 3) – Optimización + Agregar algunos 🌈Colores | de Mikhail Kulaha | marzo 2023
En esta serie de artículos, solo intentaremos recrear esta increíble animación de reloj, pero en realidad mejoralo!Animación de reloj con un poco de colorEsta es la tercera parte de nuestra serie de animación. la parte 1 es Aquíla parte 2 es Aquí
TLDR:– Se pudo encontrar el código fuente de la versión final de esta animación. Aquí.– Tenemos dos enfoques diferentes para recrear la misma animación, una con hilos paralelos y otro usando un poco un poco de matemáticas.
Hasta ahora lo hemos logrado en la Parte 1 y la Parte 2:
- crea uno rotar sin fin animación
- Dibuja una manecilla de reloj que se encoge Primero 12:00 pm y luego se estira hacia atrás durante los siguientes 12:00 pm
- Jalar 12 puntos que desaparecen y reaparecen cuando es necesario
- crear puntos armar animación
- Crear 12 en paralelo desmontar animaciones.
En esta Parte 3 vamos a:
- Crear nuevo la misma animación con un única fórmula para sustituto 12 hilos para difundir animaciones.
- cambiar de forma a los bordes redondeados y agrega algunos 🌈 Colores 🔥
- Si lo desea, detenga una animación sin fin
En la parte 2 anterior se nos ocurrió esto un algoritmo lo que tienes que tener 12 animaciones paralelas para cada uno de los puntos de propagación. Como ya habrás adivinado, esto no era óptimo. De hecho, podemos reemplazarlo con un única fórmula y no es necesario crear hilos separados. Conocemos esta animación comienza cada hora. Y en base a eso hora actual Anima desde la punta de la flecha hasta el borde exterior del círculo usando esta fórmula: positionY = halfStroke + stepHeight * it * (1 – disassembleAnimations[it].value)Donde desensamblarAnimaciones[it].value es un valor de animación de 0 a 1. Se calcula en función de valor de animaciónque comienza cada hora con la relajación y la duración adecuadas. Esa es la parte que queremos cambiar.
Contenidos
La animación básica
Podemos visualizar el movimiento de los puntos con este diagrama.Los puntos están animados de 0 a 1 comienza y termina cada hora. Cada 30 grados comienza una nueva hora. Este comportamiento se puede describir fácilmente con un fórmula de interpolación lineal. // currentDot es un índice del punto. val startAngle = currentDot * 30fval currentDeg = (animationAngle – startAngle).coerceIn(0f, 30f)currentDeg/30fMejoremos nuestro código con esta fórmula. En lugar de usar animaciones y canales paralelos, hagámoslo Cree 12 ubicaciones de puntos.val dotsPositions = Remember(animationAngle) {List(12) { currentDot ->val startAngle = currentDot * 30fval currentDeg = (animationAngle – startAngle).coerceIn(0f, 30f)currentDeg/30f}} Y usa estas posiciones en lugar de desensamblarAnimaciones valoreshoras. forEach {if (! puntos de visibilidad[it]) return@forEachval grado = it * 30frotate(grado) {val positionY = halfStroke +stepHeight * it * (1 – puntosPosiciones[it])…}}
mejorar la animación
Como vimos en la primera animación, los puntos son realmente no sigas este patrón Tú podrías terminar la transición si otro ya ha comenzado.Entonces debemos buscar algo como estoLa buena noticia es que no se requieren muchos cambios. puntos de partida son los La misma cosa. Ahora simplemente no podemos referirnos al punto final. cada 30 grados. En cambio, debemos Use 45 grados o más como queramos, para eso haremos introducir una nueva variable DegreeLimit y reescribir nuestra fórmula…. val DegreeLimit = 45f// currentDot es un índice del punto. val startAngle = currentDot * 30fval currentDeg = (animationAngle – startAngle).coerceIn(0f, gradeLimit)currentDeg/degreeLimit Y veremos eso. ¡Excelente!«¡Pero todavía no es exactamente lo mismo! ¡En la animación original, tiene este toque agradable y suave al final!”, se podría decir. Y tú tendrá razón.Deberíamos tener algo así.Tenemos una Inicio rápidopero entonces reducir la velocidad al final. En realidad, esto… se parece a un curva clásica de Bezier.Felizmente Componer marco de animación tiene exactamente lo que necesitamos para ello! relajación!Al crear especificaciones de animación, agregamos un parámetro de aceleración. En animación, por lo general está estructurado así: animation = tween(duration, easing = LinearEasing) Si observamos la interfaz de aceleración, podemos encontrar una transformación de método único, que acepta una fracción entre 0 y 1 y devuelve lo mismo 0..1 fracción con la interfaz transform.fun aplicada Easing {fun transform(fraction: Float): Float} ¡Este método es exactamente lo que necesitamos para nuestro caso! Simplemente podemos aplicar cualquier aceleración a nuestra fracción 0..1. Entonces nuestro código se ve así: val easing = LinearOutSlowInEasingval gradeLimit = 45f // currentDot es un índice del punto. val startAngle = currentDot * 30fval currentDeg = (animationAngle – startAngle).coerceIn(0f, degreeLimit)easing.transform(currentDeg/degreeLimit) ¡Así es como se verá nuestra animación! ¡Exactamente como esperábamos!¡Última animación!
Compose Animation Api nos permite especificar cualquier aceleración que queramos con un CubicBezierEasing Clase.
Por ejemplo, esta aceleración CubicBezierEasing(0f,0.3f,0.2f,1f) tiene un comienzo muy rápido y un final muy lento. Puedes jugar más con las flexibilizaciones cubic bezier en este sitio web cubic-bezier.comcubic-bezier.comExcelente! En este paso lo hemos hecho optimizar significativamente nuestra animación eliminando la creación de subprocesos innecesarios y reemplazándolos con una sola función de interpolación.
El código completo para este paso se puede encontrar aquí
Lo prometí en la Parte 2 podemos A control esta animación con un control deslizante. Y de hecho podemos. Solo necesitamos eliminar la animación infinita y pasar animationAngle como parámetro. Luego agregue un control deslizante que cambie el ángulo de animación de 0 a 720Controla la animación con un control deslizante
El código completo para este paso se puede encontrar aquí
Para ser honesto, la animación inicial aparece algo poco interesante ahora a mi 😑. Las formas cuadradas y falta de color parecen banales y poco espectaculares. Creo que podemos condimentarlo agregando esquinas redondeadas y 🌈 colorante.¡Versión coloreada! ¡Eso se ve mucho más interesante!
redondear las esquinas
Podemos redondear esquinas fácilmente especificando StrokeCap.Round en lugar del valor predeterminado StrokeCap.ButtdrawLine(…cap = StrokeCap.Round,…). El problema es que StrokeCap.Round necesita algo de espacio extra a la hora de dibujar, por lo que hay que tenerlo en cuenta. Para arreglar eso, eliminamos un medio golpe Amplio mientras dibuja.Diferencia entre tapas a tope y redondas // En lugar de val start = Offset(size.width / 2, positionY — halfStroke) // Eliminar HalfStroke val start = Offset(size.width / 2, positionY) Lo mismo se puede hacer en otros lugares para convertirse en longitud de línea y altura de punto. Fácilmente podemos dibujar un fondo de color por encima de nuestros puntos con los modos de mezcla DstOut y DstAtop. Necesitamos configurar DstOut para los elementos subyacentes y DstAtop para su superposición. // Establecer el modo de fusión como DstOut para los elementos subyacentes drawLine(…cap = StrokeCap.Round,blendMode = BlendMode. DstOut) Para colorear usamos un pincel con progresión lineal. nosotros también doblar este degradado para hacer las animaciones más interesantes¡Y eso es todo para la parte 3 amigos!En esta parte lo hicimos
- Mejorar nuestra animación con un única fórmula para Reemplazar 12 hilos para distribuir animaciones.
- También cambió de forma esquinas redondeadas y agregué algunos 🌈 Colores
Puedes ver el código fuente completo de esta animación en mi Grepositorio ithub.
Nuevamente, si te gustó este artículo, me alegraría mucho que lo aplaudieras 👏👏👏. Puedes hacerlo varias veces, hasta 15 según recuerdo. ¡Diviértete programando!