ZaatarLABS
Nous contacter →
← Tous les articles
ZaatarLABS · Ingénierie

Liquid Glass, mesuré

Deux chiffres — 120 saccades par minute et 5 — expliquent tout ce que Liquid Glass coûte réellement, et où se trouve ce coût.

4 min de lecture

Le chiffre qui m'a arrêté, c'est 120. Des saccades (hitches) par minute, Instruments ouvert, dix cartes en verre à l'écran avec l'animation de reflet en marche. Je considérais la réaction à l'inclinaison comme quasiment gratuite — elle avait l'air juste, elle suivait la lumière comme le ferait du vrai verre, elle semblait être le bon détail. Puis je l'ai mesurée.

Passer à un reflet statique sur quinze cartes a fait tomber le chiffre à cinq. Plus de cartes, aucun mouvement : une liste plus fournie et 115 saccades de moins par minute. Le verre est resté. L'animation, non.

Cet écart est tout le sujet de cet article.

Ce que j'ai écarté d'abord

L'hypothèse évidente, c'était le nombre de cartes. Plus de surfaces à l'écran, plus de travail — ce raisonnement tient pour beaucoup de problèmes de rendu, et je l'ai suivi plus longtemps que je n'aurais dû. Ce que j'ai réellement essayé : passer de 60 Hz à 30. Déplacer le reflet du rendu SwiftUI vers un CALayer. Conditionner le mouvement, pour que l'animation ne tourne que quand l'accéléromètre indique que l'appareil est immobile. Limiter la carte la plus haute pour qu'elle ne dépasse pas une hauteur fixe. Rien de tout cela n'a fait bouger les chiffres de façon significative.

La solution qui a marché était aussi la plus simple : motionEnabled = false. Reflet statique, aucune réaction à l'inclinaison, aucun échantillonnage image par image.

Ce que fait réellement le système

.glassEffect fonctionne en échantillonnant son arrière-plan. C'est ce qui lui donne l'apparence du verre plutôt que celle d'un rectangle dépoli — il lit ce qui se trouve derrière lui et applique un flou, une teinte et le reflet spéculaire sur cet échantillon. L'échantillon est en direct. Quand quoi que ce soit bouge au-dessus d'une surface en verre, le système doit recomposer l'arrière-plan de chaque surface en verre à l'écran, pas seulement de celle qui est la plus proche du mouvement.

Dix cartes. Soixante images par seconde. Une animation de reflet qui tourne au-dessus. Soixante recompositions par surface et par seconde, multipliées par chaque carte en verre de la hiérarchie de vues. 120 saccades par minute.

Quinze cartes avec un reflet statique : l'arrière-plan est échantillonné une fois et conservé jusqu'à ce que quelque chose change. Cinq saccades par minute.

Le bord spéculaire existe toujours dans la version publiée. Il est éclairé sous un angle fixe et ne bouge jamais. Ce qui a dû disparaître, c'est la réaction à l'inclinaison — la partie qui suivait l'orientation de l'appareil et faisait glisser le reflet quand vous bougiez le téléphone. La carte se lit toujours comme du verre. Elle ne réagit simplement plus à la gravité.

La surface est le vrai facteur de coût

Une fois le modèle de recomposition clair, autre chose en découlait : le coût dépend de la surface d'arrière-plan, pas du nombre de surfaces en verre.

Trente-cinq cartes étroites coûtent moins que dix cartes hautes. Ce que le système compose, c'est la surface totale de l'écran couverte de verre, et une petite carte y contribue proportionnellement moins qu'une grande, quel que soit leur nombre. Une carte de statistiques en haut d'une liste — petite, de hauteur fixe — ne coûte pas grand-chose. Une carte qui occupe presque toute la largeur de l'écran et grandit avec son contenu coûte cher.

Cela change la question de conception. Ce n'est pas « combien de surfaces en verre puis-je me permettre sur cet écran ? ». C'est « quelle part de la zone visible est en verre à une position de défilement donnée ? ».

Le problème des cartes hautes

Certaines cartes doivent être hautes. La carte des rendez-vous, par exemple, pouvait grandir indéfiniment à mesure que des éléments s'ajoutaient. Sans contrainte, sa surface d'arrière-plan grandit avec elle, et le coût par image aussi.

La solution, c'est de plafonner la hauteur. Donnez à la carte une hauteur maximale et laissez le contenu défiler à l'intérieur. Le système de verre voit une surface constante, de la taille d'une tuile, quel que soit le nombre de lignes à l'intérieur. La carte devient abordable parce que sa surface d'arrière-plan est bornée.

C'est l'une de ces contraintes qui améliorent aussi le design, indépendamment des performances. Une carte qui grandit sans limite a de toute façon tendance à pousser tout le reste hors de l'écran.

Deux détails d'implémentation à connaître

GlassEffectContainer regroupe les surfaces en verre sœurs en une seule passe de composition. Si vous avez plusieurs éléments en verre au même niveau de la hiérarchie — une rangée de cartes de statistiques, une grille —, les envelopper dans le conteneur en vaut la peine. Sans lui, chaque surface se compose indépendamment.

L'autre détail : .clipShape doit venir avant .background dans la chaîne de modificateurs.

// Wrong — the background bleeds past the corners
.background(material)
.clipShape(RoundedRectangle(cornerRadius: 16))

// Right
.clipShape(RoundedRectangle(cornerRadius: 16))
.background(material)

Le matériau verre ne découpe pas ses enfants. Une ligne qui peint son propre arrière-plan dessinera des coins carrés au-delà de la forme arrondie de la carte si le découpage vient après. Je l'ai découvert à mes dépens sur une liste avec des lignes internes.

Ce que ça a coûté au design

La réaction à l'inclinaison a disparu. C'était le comportement le plus évidemment « verre » — le reflet qui bouge quand vous bougez le téléphone — et c'est ce à quoi vous renoncez quand le profileur affiche 120.

Ce qui est resté : le corps dépoli, le bord spéculaire, le dégradé angulaire du reflet. La carte se lit comme du verre. Elle ne se comporte pas comme du verre au sens physique.

L'autre contrainte imposée par les mesures : les cartes de statistiques restent en verre transparent, jamais teinté. Une teinte qui fonctionne sur une carte aux libellés blancs rend invisible un texte de la couleur principale. Le code couleur a sa place dans les données — la sparkline, l'indicateur —, pas dans la surface.

Le fichier est la documentation

LiquidGlassCard.swift est copié à l'identique dans The Smart Dentist, Billing et Coach. C'est délibéré. Les règles de performance voyagent avec le fichier au lieu de vivre dans une note quelque part. Le contexte du passage de 120 à 5 se trouve dans le même source que le code, à côté des réglages et des commentaires, pour que la prochaine personne qui l'ouvre n'ait rien à redécouvrir.

Les chiffres sont le document de conception. Tout le reste n'est que commentaire.

Écrit par Omar Al Homaidi · ZaatarLABS · @zaatarlabs