Todo frame perfeito
(tonsky.me)- A UI é quase a única superfície pela qual o usuário julga a qualidade de um app, e a confiança se constrói quando, em qualquer momento em que se tire uma captura de tela, o estado da tela faz sentido
- Uma UI bem acabada sinaliza que o desenvolvedor investiu tempo em refinamento e vira uma heurística razoável de que a qualidade do código também foi lapidada no mesmo nível
- O critério real é eliminar piscadas brancas entre transições de tela, carregamento parcial, rearranjos durante o carregamento, inconsistências em mensagens de estado e animações imprecisas
- Mesmo que os estados inicial e final sejam bons, se os frames intermediários estiverem desalinhados, isso passa a sensação de que os componentes não estão sincronizados e, como no caso do Photos, pode criar uma sensação falsa mesmo quando não há mudança real
- As animações devem ajudar a entender a transição, e é preciso cuidar não só do início e do fim, mas de todos os frames entre eles para que a UI pareça uma ferramenta de precisão
Princípio central
- O objetivo explícito do Wayland, “every frame is perfect”, é uma meta técnica para retomar o controle em meio à complexidade da stack moderna de GPU
- O mesmo princípio se aplica à UI: qualquer captura de tela do app, em qualquer momento, deve parecer natural e consistente
- Como o usuário não pode ver o código, a UI se torna a única superfície pela qual ele avalia a qualidade do app
- Quando a UI é bem polida, isso sinaliza que o desenvolvedor dedicou tempo ao acabamento e leva à conclusão de que o código provavelmente foi refinado em nível semelhante
Critérios práticos e exemplos
- Para ter frames perfeitos, não pode haver piscadas brancas entre telas, nem conteúdo parcialmente carregado ou rearranjos de layout durante o carregamento
- O estado interno da UI deve ser consistente; uma parte não pode dizer “1 update available” enquanto outra diz “Checking for updates...”
- As animações costumam ser esquecidas, e mesmo que os estados inicial e final estejam bons, se o meio for estranho, uma captura intermediária vira um frame que não faz sentido
- No caso do Safari, o texto de placeholder se move a partir do centro, mas o cursor é animado a partir da posição à esquerda, criando a sensação de que os dois componentes não estão sincronizados entre si
- No caso do Photos, ao alternar entre os modos Crop e Adjust, a foto volta imediatamente para o lugar, mas a borda de corte é animada, criando uma falsa sensação de que algo mudou sutilmente durante a transição de modo
- No caso da UI de busca, a animação, que deveria ajudar a entender a transição, acaba tornando mais difícil acompanhar o movimento da lupa
- No caso do Youtube, até uma tarefa simples como mover um retângulo de uma posição para outra produz um movimento estranho e, independentemente do motivo, o resultado é um frame imperfeito
- Incluindo até a animação de zoom do app Preview, o ponto central é que é preciso prestar atenção não só aos estados inicial e final, mas também a todos os momentos entre eles
2 comentários
Opiniões no Hacker News
Alguns dos exemplos citados pelo autor realmente são animações ruins, mas é difícil concordar com a premissa do texto
Computação gráfica é uma área que explora as características do sistema visual humano, e percebemos coisas em movimento de forma diferente de coisas paradas. Se isolado, um frame “errado” pode na verdade parecer o melhor dentro do fluxo real do tempo
Fazendo uma analogia com cinema: um tracking shot rápido pode fazer frames individuais parecerem ruins por causa do motion blur, e um plano grande angular pode fazer objetos parecerem “errados” por causa da distorção, mas se isso produz o efeito artístico pretendido no cinema, então foi a escolha certa
Se você adiciona o blur correto ao movimento, ele pode parecer mais nítido, mas obviamente não fica mais nítido quando visto como imagem estática. O ponto principal é que o motion blur correto garante que, naquela velocidade, o movimento pareça tão nítido quanto o detalhe em movimento que um humano consegue perceber. Portanto, é errado avaliar um frame congelado com motion blur com base em nitidez ou legibilidade
O restante do texto foca nos detalhes de implementação, mas perde a chance de perguntar se algumas dessas animações deveriam existir para começo de conversa. Movimento pode ser uma boa affordance quando usado com moderação, mas agora já passou do excesso e em alguns casos invade o campo de visão e a carga cognitiva do usuário. Designers e PMs tratam isso como um sinal de “UX moderna e refinada”, mas em muitos casos degenerou em decoração de moda que imita bom design, em vez de ser bom design de fato
Algumas das animações mostradas claramente parecem passíveis de melhora. A IA parece bastante promissora para levar esse tipo de pequeno prazer mais longe, porque antes era difícil gastar tempo com isso por ser prioridade baixa
É diferente um frame intermediário da animação parecer um pouco “estranho” mas ainda fazer sentido lógico, de um estado intermediário realmente não fazer sentido e ser apenas resultado de ninguém se importar com o que acontece durante a animação. Nesse segundo caso, talvez fosse melhor remover a animação ou simplificá-la
Gosto da perspectiva do texto de usar o acabamento da UI como indicador indireto da qualidade do software, e ele acerta ao apontar animações ruins. Mas consistência por frame não é a melhor régua para medir o quanto uma animação é “boa”
Alguns dispositivos ainda estão no Sonoma, e só dá para dizer que continua regredindo
A caixa de diálogo de salvar balança um pouco, mas não é tão confusa quanto no exemplo. O botão do Notes se move entre os painéis com suavidade perfeita. Se você focar e desfocar a barra do Safari repetidamente, às vezes a animação quebra, mas o cursor fica exatamente sincronizado com o texto e só entra em fade depois que o texto termina de se mover para a esquerda. O bug do Preview também parece ser um problema recente, e não consigo reproduzi-lo
https://streamable.com/kx7op6
Sinto falta da época em que empresas como Apple, Sony e IBM se importavam com detalhes minúsculos. A Apple, em especial, conquistou o valor que tem hoje com o iPhone, que na época não fazia nada especialmente incrível em comparação com Windows Mobile ou os PDAs Symbian e até ficava atrás em funcionalidade em alguns aspectos, mas era um dispositivo totalmente touchscreen que não dava vontade de jogar na parede depois de alguns minutos de uso. Essas animações de agora trazem exatamente de volta a sensação de Windows Mobile e Symbian
Lembro do quanto o Steve gostava das animações do OS X. No palco, ele as reproduzia em câmera lenta várias vezes. As de hoje estão num nível que não seria estranho entregá-las às mesmas pessoas que tiveram o destino do responsável pela antena do iPhone 4
Parece mesmo que uma UI sem esses frames imperfeitos seria melhor, mas agora eu queria que alguém corrigisse cada clipe e mostrasse como ficaria de verdade
Ao mesmo tempo, também fica a dúvida de por que tudo precisa de movimento. Pelo que entendo, movimento faz sentido quando a UI muda de forma sutil em uma área diferente daquela em que o usuário iniciou a ação, como um toast
Muitas das transições mostradas aqui parecem desnecessárias, e provavelmente ficariam boas o bastante mudando de forma instantânea, com rearranjo imediato
O cursor aparece à esquerda porque é ali que o usuário de fato começa a digitar. Quem conhece a UI provavelmente vai olhar para aquele ponto. Fazer o cursor aparecer no meio da tela e depois movê-lo seria desnecessário e distrativo
O texto placeholder desliza para a esquerda para chamar a atenção de usuários menos familiarizados
$BRANDé superior às alternativasA maior parte dos exemplos provavelmente pareceria melhor sem animação. Se apertei um botão, basta me mostrar o resultado. Em vez de dançar antes de mostrar, queria que simplesmente mostrasse
Sem movimento, muitas vezes o cérebro precisa varrer a página inteira de novo a cada atualização
Acho que a argumentação deste texto foi apresentada de forma fraca. Também não há alternativa melhor, nem se explica de fato por que o que foi mostrado é negativo para o usuário. Pode até ser negativo, mas se parece com aquela forma vazia de criticar apontando para um smear frame da mídia ou para um ponto de transição
O critério de que “todos os frames precisam fazer sentido” também é difícil de sustentar. Acho impossível, e queria perguntar como isso seria feito se a ideia fosse manter todos os frames perfeitos até durante o redimensionamento da janela
O próprio autor também parece achar mais fácil apontar frames defeituosos do que colocar em prática o critério que defende. Se você clicar no link do cabeçalho do blog, a animação roda depois que o clique termina. Se olhar os projetos de UI dele, também há lugares onde texto e objetos não ficam dentro do contêiner. Se vai dizer que esses princípios devem ser seguidos, então também deveria conseguir mostrá-los na prática
Se fosse um texto melhor escrito, teria se concentrado em por que as coisas apresentadas são ruins para o usuário final e em como lidar com isso no lugar. Uma boa crítica inclui não só o “o quê”, mas também o porquê e o como
O texto está propondo ideias, não soluções. Não perceber isso e criticá-lo montando vários espantalhos argumentativos acaba sendo justamente esse erro
Mais importante ainda é que o texto não foi escrito de forma categórica. Foi escrito com cuidado, com expressões como “I think”, “Next thought:”, “Probably” e “So yeah.”. É uma pessoa compartilhando o que pensa, e é um pensamento bastante elaborado, a ponto de poder levar várias pessoas razoáveis a pensar em direção parecida
Não há motivo para dizer que o autor necessariamente tinha de apresentar uma solução. Esse critério é estranho e irracional
Também não pega bem atacar o site do autor. Diferenças de gosto são bem conhecidas, e punir uma contribuição conceitual por estar à frente da técnica real é algo bem desagradável
Uma crítica melhor teria sido mais generosa, de um jeito mais alinhado ao espírito desta comunidade
Vi algumas reações dizendo que gostariam que o autor incluísse exemplos de solução. Ele escreveu recentemente um texto muito parecido com este e, assim como aqui, detalhou os problemas de animação e depois explicou como os melhorou
Se tiver curiosidade, dá para ver aqui: https://www.thisischris.dev/projects/project-6/
Acho melhor um frame imperfeito agora do que um frame perfeito mais tarde. Em toda UI, a latência deveria ser a prioridade máxima. Se a latência for baixa o suficiente, a interface parece uma extensão do próprio corpo e a carga cognitiva diminui. Animações são especialmente ruins nisso, porque adicionam centenas de milissegundos de atraso
Eu queria que houvesse exemplos positivos junto com os negativos. Do jeito que está, a conclusão a que cheguei é só que se deve evitar animação, mas não acho que isso seja realmente o que o autor quer dizer
Não é raro que boas animações usem um pouco de trapaça durante o movimento, em vez de parecerem perfeitas em todos os frames. Como os smear frames dos cartoons: se você parar no frame errado fica estranho, mas dentro da animação inteira aquilo torna o movimento visualmente convincente
Não sou desenvolvedor, mas dava para sentir áreas em que ícones ou janelas não eram posicionados ou movidos como antes, ou como intuitivamente deveriam ser
Essa sensação de remendo não mudou com o tempo. Existem tantos exemplos pelo sistema e pelos apps que quase dá vontade de dizer que “sempre foi assim”, mas não foi. A Apple estabeleceu um padrão, esse padrão era alto e a qualidade era excelente
Parece que, para atingir com SwiftUI o mesmo layout de UI ou a mesma animação, entra muita gambiarra
Por fim, algo em que penso com frequência é que criação analógica era muito difícil, e ainda é. No digital, a gente sempre achou que depois daria para voltar e arrumar, mas na prática isso muitas vezes não acontece, e é triste ver coisa ruim sendo empilhada em cima de coisa pior
[1]: https://youtu.be/vIdeGmN__Pw?t=550
Um app sem nenhuma animação pareceria terrível. Se você tiver Android, pode testar por conta própria mudando a velocidade da animação para 0x nas opções de desenvolvedor. A mudança imediata incomoda, e o cérebro leva quase 1 segundo para processar o que aconteceu; esse processo pode até ser mais lento do que quando há animação
Minha configuração é 0,5x e acho suficiente. Ainda é rápido, mas dá para ver os apps abrindo e fechando
O problema do 0x é que parece se aplicar só a uns 90% da UI. Algumas coisas ainda continuam animadas, e por isso o ritmo fica bem estranho
Em 0,5x, as coisas que estranhamente não são afetadas pela configuração de velocidade da animação incomodam menos
Se funcionasse direito, eu usaria 0x
Se for necessário, prefiro gastar 1 segundo com processamento, e na verdade nem acho que isso seja necessário. É muito melhor do que perder 1 segundo por causa da animação toda vez que um app muda de página, e tudo parece melaço ao navegar
Gostei da identificação com este texto, mas eu queria que também houvesse exemplos positivos. O tom não soou como reclamação, mas, para alguém que não sabe muito sobre como compor uma boa UI, não senti que fiquei mais perto de saber o que tomar como estrela-guia
Se tiver curiosidade, dá para ver aqui: https://www.thisischris.dev/projects/project-6/
Opiniões no Lobste.rs
Acho que a premissa básica deste texto está errada. Ninguém usa esse tipo de app quadro a quadro
Mesmo em uma aula básica de animação, você aprende que a forma como percebemos movimento é diferente da forma como percebemos imagens estáticas. Se procurar uma demonstração de "squash and stretch", verá que, quadro a quadro, as dimensões de um objeto podem parecer absurdas isoladamente, mas funcionam lindamente em movimento
Ela pode até mostrar o estado do programa de forma incorreta, como no exemplo de recorte. O usuário precisa praticamente desligar o cérebro por um terço de segundo enquanto a UI é remontada, e só então pode continuar usando o programa
Acho que perfeição de quadros não é isso que o projeto Wayland quer dizer
Está mais perto de detalhes técnicos de nível mais baixo, como redimensionamento de janela. Por exemplo, quando o conteúdo é redimensionado de forma assíncrona, quando a sincronização vertical quebra e surgem tearing ou artefatos diagonais estranhos na tela, ou quando o relatório de regiões danificadas é feito em subáreas retangulares
Claro, seria ótimo se tanto os detalhes de baixo nível quanto as animações de alto nível fossem perfeitos quadro a quadro
Digamos que você queira testar esse tipo de animação e escrever testes para garantir que essa propriedade não se quebre com o tempo
Quais são hoje as técnicas mais modernas para testar esse tipo de propriedade em apps web e apps nativos? Há categorias específicas de teste que você gostaria de escrever, mas que na prática são impossíveis ou muito difíceis por não conseguir controlar o event loop?
Ou então registrar a transição inteira como PNG animado com uma ferramenta como Paparazzi para fazer testes automatizados de regressão
Aí você valida os dois pontos separadamente e, no final, só verifica o estado final. A animação não deveria ficar presa a uma entrada de tempo fixa, mas poder ser conduzida passo a passo a partir de fora
Acho que o exemplo do YouTube é quase um caso clássico de View Transitions
É uma abordagem declarativa do tipo “quando este elemento mudar, transforme-o automaticamente”, e o resultado acaba sendo uma transição tecnicamente impressionante, mas meio molenga, com elementos flutuando pela tela e se deformando uns nos outros
É uma tecnologia muito legal, mas quase nunca vi isso ficar realmente bom além de pequenos efeitos de destaque durante a navegação. Para não ficar distrativo demais, é preciso usar com muita moderação