Animations dans les applications iOS nées sur le serveur



Il y a six mois, nous avons présenté l'une des fonctionnalités les plus impressionnantes de Badoo: la diffusion en direct . Entre autres, il permet aux utilisateurs d'exprimer leur gratitude à leurs streamers préférés sous forme de cadeaux. Nous voulions rendre ces cadeaux aussi brillants et attrayants que possible, alors nous avons décidé de les faire revivre - en d'autres termes, d'animer. Et pour le rendre encore plus intéressant, nous avons prévu de mettre à jour les cadeaux et les animations toutes les quelques semaines.

Les ingénieurs iOS doivent avoir deviné quels volumes de travail sont en cause: pour supprimer les anciennes et ajouter de nouvelles animations, il faut effectuer de nombreuses actions côté client. Pour ce faire, les équipes Android et iOS doivent être impliquées dans chaque version et, avec le temps nécessaire pour approuver la mise à jour dans l'App Store, cela signifie que le lancement de chaque version avec des animations mises à jour peut prendre plusieurs jours. Cependant, nous avons réussi à résoudre ce problème, et maintenant je vais vous dire comment.

Architecture de la solution


À cette époque, nous savions déjà comment exporter des animations Adobe After Effects (ci-après - AAE) dans un format compréhensible pour notre application iOS à l'aide de la bibliothèque Lottie. Cette fois, nous sommes allés un peu plus loin: nous avons décidé de stocker toutes les animations pertinentes sur le serveur et de les télécharger au besoin.



Un exemple de véritable animation dans notre application, obtenu de cette façon:



Cependant, dans cet article à titre d'exemple, je vais prendre une animation simple que j'ai créée moi-même. Ce n'est pas aussi créatif que dans Badoo, mais c'est tout à fait approprié pour démontrer notre approche.

Exporter des animations


Le projet AAE que j'utilise peut être trouvé avec d' autres sources sur GitHub . Ainsi, en ouvrant le projet situé dans _raw/animations/Fancy/Fancy.aep , vous verrez une fenêtre:



Maintenant, je ne parle pas du processus de création d'animations en AAE, mais de la façon d'importer des animations existantes depuis AAE dans un format adapté à une application iOS à l'aide du plug- in Bodymovin .

Après avoir installé le plugin, ouvrez-le en sélectionnant Fenêtre / Extensions / Bodymovin dans le menu :



La fenêtre Bodymovin apparaît, dans laquelle vous pouvez sélectionner l'animation à exporter, un dossier pour enregistrer le fichier résultant et ouvrir les paramètres d'exportation:



Dans les paramètres d'animation, nous pouvons demander à Bodymovin d'inclure des ressources dans le fichier JSON en sélectionnant Actifs / Inclure dans json :



Enfin, en appuyant sur le bouton Rendu , nous exportons et enregistrons la composition animée sélectionnée dans un fichier.

Stocker des animations sur le serveur


Supposons que nous téléchargions des fichiers JSON animés rendus sur un serveur Web. Dans notre cas, pour plus de simplicité, je les ai mis dans le référentiel du projet sur GitHub. Des animations sont disponibles ici:



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

ID d'animation:

  • clouds.json
  • fireworks.json


Remarque: Vous cherchez un serveur Web Swift pour des animations? La solution est disponible ici , et une explication détaillée se trouve dans cet article .


Nous avons donc un serveur fonctionnel avec des animations, il est donc temps de passer à la partie la plus excitante: le rendu des animations à l'écran.

Affichage d'animation


Maintenant, je vous conseille d'ouvrir un projet de démonstration pour notre application iOS , car il contient tout le code et les paramètres nécessaires.

Télécharger des animations


Étant donné que l'API REST pour recevoir des données est déjà prête, il est temps d'introduire le protocole du fournisseur de données et d'ajouter son implémentation, qui télécharge les données du serveur:

 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       }   } } 


Cette classe de fournisseur de données nous permet de télécharger des animations au format JSON depuis le serveur sur demande et de les stocker en mémoire pour le rendu dans l'interface utilisateur. Supposons que nous suivions le modèle MVVM - alors il est facile de l'utiliser dans l'entité ViewModel comme suit:

  // ... 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 met à jour la propriété de l'animation sélectionnée lorsqu'il reçoit la réponse HTTP correcte d'un serveur avec un objet JSON non vide. Ces données sont utilisées par la couche de présentation pour afficher l'animation.

Couche de présentation


Maintenant, nous pouvons utiliser le ViewModel pour accéder aux données d'animation et les afficher sur l'interface utilisateur à l'aide du gestionnaire d'action intégré au robinet attaché au bouton:

 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()   } } 


Lorsqu'un bouton est cliqué, l'instance LOTAnimationView est mise à jour avec les dernières données du ViewModel .

Voici à quoi ça ressemble:



C’est tout. Maintenant, l'application affiche l'animation téléchargée à partir de notre API REST
(depuis le serveur).

Conseils et limitations


Astuces:

  • AAE prend en charge la plupart des types d'objets, y compris les images raster et vectorielles;
  • Bodymovin vous permet d'incorporer toutes les ressources dans le fichier JSON final à l'aide de Base64, et grâce à cela, vous pouvez éviter de charger les ressources séparément du côté client;
  • Vous pouvez dessiner directement dans un vecteur au format AAE ou simplement importer des images vectorielles au format Adobe Illustrator.

Malheureusement, je n'ai pas pu importer de fichiers SVG dans AAE (j'ai essayé!).

Vous pouvez en apprendre plus sur les astuces et résoudre les problèmes possibles dans cet article intéressant de mon collègue Radoslaw Sesiva .

Conclusion


Alors, que nous apporte le téléchargement d'animations depuis le serveur? L'avantage le plus évident de cette approche est la possibilité de partager tous les participants au processus de mise à jour de l'animation. En d'autres termes, pour publier une nouvelle animation sympa, les concepteurs doivent simplement fournir à l'équipe du serveur le fichier JSON approprié. Pour supprimer l'animation sur le client, supprimez-la simplement du serveur. Facile et rapide.

Il est également très cool que les mêmes fonctions puissent être implémentées sur toutes les plates-formes prises en charge (iOS, Android, Web), sans apporter de modifications au protocole client-serveur, au code serveur et aux fichiers d'animation eux-mêmes directement sur le client.

C’est tout. Merci de votre attention!


Liens utiles


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


All Articles