Animaciones en aplicaciones iOS nacidas en el servidor



Hace seis meses, presentamos una de las características más impresionantes de Badoo: la transmisión en vivo . Entre otras cosas, permite a los usuarios expresar gratitud a sus serpentinas favoritas en forma de regalos. Queríamos hacer estos regalos lo más brillantes y atractivos posibles, por lo que decidimos revivirlos, en otras palabras, animarlos. Y para hacerlo aún más interesante, planeamos actualizar regalos y animaciones cada pocas semanas.

Los ingenieros de iOS deben haber adivinado qué volúmenes de trabajo están en cuestión: para eliminar animaciones antiguas y agregar nuevas animaciones, es necesario realizar muchas acciones en el lado del cliente. Para hacer esto, los equipos de Android e iOS deben participar en cada lanzamiento y, junto con el tiempo requerido para aprobar la actualización en la App Store, esto significa que el lanzamiento de cada lanzamiento con animaciones actualizadas puede llevar varios días. Sin embargo, logramos resolver este problema, y ​​ahora te diré cómo.

Arquitectura de soluciones


En ese momento, ya sabíamos cómo exportar animaciones de Adobe After Effects (en adelante, AAE) en un formato comprensible para nuestra aplicación iOS usando la biblioteca Lottie. Esta vez fuimos un poco más allá: decidimos almacenar todas las animaciones relevantes en el servidor y descargarlas según sea necesario.



Un ejemplo de animación real en nuestra aplicación, obtenida de esta manera:



Sin embargo, en esta publicación como ejemplo, tomaré una animación simple que yo mismo creé. No es tan creativo como en Badoo, pero es bastante adecuado para demostrar nuestro enfoque.

Exportar animaciones


El proyecto AAE que utilizo se puede encontrar junto con otras fuentes en GitHub . Entonces, al abrir el proyecto ubicado en _raw/animations/Fancy/Fancy.aep , verá una ventana:



Ahora no estoy hablando del proceso de creación de animaciones en AAE, sino de cómo importar animaciones existentes de AAE a un formato adecuado para una aplicación iOS usando el complemento Bodymovin .

Después de instalar el complemento, ábralo seleccionando Ventana / Extensiones / Bodymovin en el menú :



Aparecerá la ventana Bodymovin, en la que puede seleccionar la animación para exportar, una carpeta para guardar el archivo resultante y abrir la configuración de exportación:



En la configuración de animación, podemos pedirle a Bodymovin que incluya recursos en el archivo JSON seleccionando Activos / Incluir en json :



Finalmente, al presionar el botón Renderizar , exportamos y guardamos la composición animada seleccionada en un archivo.

Almacenar animaciones en el servidor


Supongamos que cargamos archivos JSON animados renderizados a un servidor web. En nuestro caso, por simplicidad, los puse en el repositorio del proyecto en GitHub. Las animaciones están disponibles aquí:



Enlace base https://raw.githubusercontent.com/chupakabr/server-provided-animations/master/_raw/rendered-animations/

ID de animación:

  • clouds.json
  • fireworks.json


Nota: ¿Busca un servidor web Swift para animaciones? La solución está disponible aquí , y una explicación detallada está en este artículo .


Entonces, tenemos un servidor que funciona con animaciones, por lo que es hora de pasar a la parte más emocionante: renderizar animaciones en la pantalla.

Pantalla de animación


Ahora le aconsejo que abra un proyecto de demostración para nuestra aplicación iOS , ya que contiene todo el código y la configuración necesarios.

Descargar animaciones


Dado que la API REST para recibir datos ya está lista, es hora de presentar el protocolo del proveedor de datos y agregar su implementación, que descarga los datos del servidor:

 import Lottie protocol AnimationsProviderProtocol {   typealias Completion = (_ animation: LOTComposition?) -> Void   func loadAnimation(byId id: String, completion: @escaping Completion) } final class ServerAnimationProvider: AnimationsProviderProtocol {   private let endpoint: URL   init(endpoint: URL) {       self.endpoint = endpoint   }   func loadAnimation(byId id: String, completion: @escaping Completion) {       let path = "/\(id).json"       guard let animationUrl = URL(string: path, relativeTo: self.endpoint) else {           completion(nil)           return       }       URLSession.shared.invalidateAndCancel()       let task = URLSession.shared.dataTask(with: animationUrl) { (data, response, error) in           guard error == nil, let data = data, let json = self.parseJson(from: data) else {               completion(nil)               return           }           let animation = LOTComposition(json: json)           completion(animation)       }       task.resume()   }   private func parseJson(from data: Data?) -> [AnyHashable : Any]? {       guard let data = data else { return nil }       do {           let json = try JSONSerialization.jsonObject(with: data, options: []) as? [AnyHashable : Any]           return json       } catch {           return nil       }   } } 


Esta clase de proveedor de datos nos permite descargar animaciones en el formato JSON desde el servidor a pedido y almacenarlas en la memoria para procesarlas en la interfaz de usuario. Supongamos que seguimos el patrón MVVM, entonces es fácil usarlo en la entidad ViewModel siguiente manera:

  // ... private let animationProvider: AnimationsProviderProtocol private(set) var animationModel: LOTComposition? // … func loadAnimation(byId animationId: String) {     self.animationProvider.loadAnimation(byId: animationId) { [weak self] (animationModel) in         self?.animationModel = animationModel     } } // ... 


ViewModel actualiza la propiedad de la animación seleccionada cuando recibe la respuesta HTTP correcta de un servidor con un objeto JSON no vacío. La capa de presentación utiliza estos datos para mostrar la animación.

Capa de presentación


Ahora podemos usar ViewModel para acceder a los datos de animación y mostrarlos en la interfaz de usuario utilizando el controlador de acción de toque incorporado adjunto al botón:

 class ViewController: UIViewController {   // ...   @IBOutlet weak var animationContainer: UIView!   override func viewDidLoad() {       super.viewDidLoad()       // ...       self.animationView = {           let view = LOTAnimationView(frame: self.animationContainer.bounds)           self.animationContainer.addSubview(view)           return view       }()   }   @IBAction func onPlayAnimationAction(_ sender: Any) {       self.animationView.stop()       self.animationView.sceneModel = self.viewModel.animationModel       self.animationView.play()   } } 


Cuando se hace clic en un botón, la instancia de LOTAnimationView se actualiza con los últimos datos de ViewModel .

Así es como se ve:



Eso es todo Ahora la aplicación muestra la animación descargada de nuestra API REST
(del servidor)

Consejos y limitaciones


Trucos:

  • AAE admite la mayoría de los tipos de objetos, incluidas imágenes ráster y vectoriales;
  • Bodymovin le permite incrustar todos los recursos en el archivo JSON final utilizando Base64 y, gracias a esto, puede evitar cargar recursos por separado en el lado del cliente;
  • Puede dibujar directamente en un vector en AAE o simplemente importar imágenes vectoriales en formato Adobe Illustrator.

Desafortunadamente, no pude importar archivos SVG en AAE (¡lo intenté!).

Puedes aprender más sobre trucos y resolver posibles problemas de este interesante artículo de mi colega Radoslaw Sesiva .

Conclusión


Entonces, ¿qué nos da la descarga de animaciones del servidor? El beneficio más obvio de este enfoque es la capacidad de compartir todos los participantes en el proceso de actualización de la animación. En otras palabras, para lanzar una nueva animación genial, los diseñadores solo necesitan proporcionar al equipo del servidor el archivo JSON apropiado. Para eliminar la animación en el cliente, simplemente elimínela del servidor. Fácil y rapido.

También es genial que las mismas funciones se puedan implementar en todas las plataformas compatibles (iOS, Android, Web), sin realizar cambios en el protocolo cliente-servidor, el código del servidor y los archivos de animación directamente en el cliente.

Eso es todo Gracias por su atencion!


Enlaces utiles


Source: https://habr.com/ru/post/439368/


All Articles