Como o CAAnimation me ajudou a conquistar meu medo de criar animações


Este artigo se concentra no uso do CA Animations no iOS para criar animações suaves.

Nos meus primeiros dias de trabalho com o iOS, eu ficava muito nervoso sempre que um designer me procurava e solicitava alguma animação no aplicativo em que estavam trabalhando.

Craaaaap

Eu achava muito fácil criar o design para animações – mas implementá-lo, por outro lado, era uma tarefa muito difícil.

Gostaria de obter ajuda do Google, StackOverflow e de meus colegas para a implementação.
Durante o processo, desenvolvi uma fobia de animações e sempre tentei evitá-las. Mas tudo isso mudou um dia.

Localizando CAAnimation

Uma vez, tive que animar uma sequência de imagens em uma exibição. Então, qual foi o meu primeiro passo? Obviamente, StackOverflow!

O primeiro link recebeu o código.

let image_1 = UIImage(named: "image-1")!
let image_2 = UIImage(named: "image-2")!
let image_3 = UIImage(named: "image-3")!
let images = [image_1, image_2, image_3]
let animatedImage = UIImage.animatedImage(with: images, duration: 2.0)
imageView.image = animatedImage

Parece bem direto, certo? Se fosse assim tão simples, eu não estaria escrevendo este artigo.

É isso que a animação foi necessária.

Meta final

E como provavelmente ficou claro, eu não estava nem perto disso. Eu estava travado. Como eu deveria fazer tantas personalizações nessa animação e sincronizar todas elas?

Então meu colega me disse para tentar CAAnimation. Eu li e tentei em um projeto de amostra. Para minha surpresa, era tão fácil e poderoso de usar.

O que é animação principal?

A Animação central ajuda você a executar várias animações com quase zero uso da CPU.
Ele oferece alta taxa de quadros e muitas personalizações que você pode usar com muito pouco código.

Você pode encontrar mais detalhes nos documentos aqui: https://developer.apple.com/documentation/quartzcore

Em poucas horas, consegui fazer uma implementação básica.

func addAnimation(firstImageView: UIImageView, secondImageView: UIImageView) {
        let basicAnimation1 = getBasicAnimation(withInitialPostion: centerPosition, finalPos: finalPosition)
        firstImageView.layer.add(basicAnimation1, forKey: "position")        
        let basicAnimation2 = self.getBasicAnimation(withInitialPostion: self.initalPosition, finalPos: self.centerPosition)
        secondImageView.layer.add(basicAnimation2, forKey: "position")
        self.addNextImage(forImageView: firstImageView)
    }
    func getBasicAnimation(withInitialPostion initialPos: CGPoint, finalPos: CGPoint) -> CABasicAnimation {
        let basicAnimation = CABasicAnimation(keyPath: "position")
        basicAnimation.fromValue = NSValue(cgPoint: initialPos)
        basicAnimation.toValue = NSValue(cgPoint: finalPos)
        basicAnimation.duration = 1
        basicAnimation.isRemovedOnCompletion = false
        basicAnimation.fillMode = CAMediaTimingFillMode.forwards
        basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        return basicAnimation
    }

Animação básica da CA

Para esta implementação, eu usei CABasicAnimation.

o CABasicAnimation A classe ajuda a animar uma propriedade de camada (que pode ser cor de fundo, opacidade, posição, escala) entre dois valores. Você apenas precisa fornecer um valor inicial e final, e o restante será resolvido. A animação começa imediatamente no próximo ciclo de execução, conforme descrito mais detalhadamente. aqui.

Agora, voltando ao nosso problema.

Para implementar isso, tirei duas visualizações de imagem e adicionei duas imagens separadas para elas. Continuei animando-os um após o outro usando o CAAnimation.

Você pode encontrar a implementação completa do código aqui.

Se você examinar meu último gif de implementação, verá algo errado. Antes de a primeira imagem sair da vista, por exemplo, a caixa de presente, ela é imediatamente alterada para fones de ouvido e depois sobe.

Por que isso está acontecendo?

Como assim que adicionamos a animação à visualização de imagem, estamos adicionando a próxima imagem a essa visualização (linhas número 5 e 6).

private func addAnimation(firstImageView: UIImageView, secondImageView: UIImageView) {
    let basicAnimation1 = getBasicAnimation(withInitialPostion: centerPosition, finalPos: finalPosition)
    firstImageView.layer.add(basicAnimation1, forKey: "position")    
    let basicAnimation2 = self.getBasicAnimation(withInitialPostion: self.initalPosition, finalPos: self.centerPosition)
    secondImageView.layer.add(basicAnimation2, forKey: "position")
    self.addNextImage(forImageView: firstImageView)
}

Aqui estamos lutando com a questão de como sincronizar as duas imagens na animação. Mas sempre há uma solução com o CAAnimation.

Transações da CA

O CA Transactions nos ajuda a sincronizar várias animações juntos. Isso garante que todas as animações reunidas sejam iniciadas ao mesmo tempo.

Além disso, você pode atribuir um bloco de conclusão às suas animações, que será executado quando todas as suas animações em um pacote forem concluídas.

Você pode ler mais sobre isso aqui.

private func addAnimation(firstImageView: UIImageView, secondImageView: UIImageView) {
    CATransaction.begin()
    CATransaction.setCompletionBlock {
        self.addNextImage(forImageView: firstImageView)
    }
    let basicAnimation1 = getBasicAnimation(withInitialPostion: centerPosition, finalPos: finalPosition)
    firstImageView.layer.add(basicAnimation1, forKey: "position")
    CATransaction.commit()
    
    let basicAnimation2 = self.getBasicAnimation(withInitialPostion: self.initalPosition, finalPos: self.centerPosition)
    secondImageView.layer.add(basicAnimation2, forKey: "position")
}

Você começa escrevendo CATransaction.begin (). Em seguida, escreva todas as suas animações que você deseja fazer em sincronia. Em seguida, chame CATransaction.commit (), que iniciará a animação no bloco.

Vamos ver como fica nossa animação agora.

Transação da CA

Uma última coisa que eu precisava fazer era adicionar o efeito Spring na animação. Felizmente, o CAAnimation também tinha uma solução para isso.

Animação da Primavera da CA

O CA Spring Animation, quando adicionado a uma camada, fornece um efeito semelhante a uma mola, para que pareça ser puxado em direção a um destino por uma mola.

Quanto mais a camada estiver do alvo, maior será a aceleração em direção a ela.
Ele permite o controle de atributos físicos, como amortecimento e rigidez da mola. – Documentos

Você pode ler mais sobre isso na documentação da Apple: https://developer.apple.com/documentation/quartzcore/caspringanimation

Vamos implementá-lo em nosso código existente.

private func getSpringAnimation(withInitialPostion initialPos: CGPoint, finalPos: CGPoint) -> CASpringAnimation {
    let basicAnimation = CASpringAnimation(keyPath: "position")
    basicAnimation.fromValue = NSValue(cgPoint: initialPos)
    basicAnimation.toValue = NSValue(cgPoint: finalPos)
    basicAnimation.duration = basicAnimation.settlingDuration
    basicAnimation.damping = 14
    basicAnimation.initialVelocity = 5
    basicAnimation.isRemovedOnCompletion = false
    basicAnimation.fillMode = CAMediaTimingFillMode.forwards
    return basicAnimation
}

Voila

Meu trabalho é feito aqui.

Para Concluir, Aqui estão algumas vantagens do uso do CA Animations

  • Fácil de usar e implementar
  • Muitas personalizações disponíveis
  • Pode sincronizar várias animações
  • Uso quase zero da CPU

Estas são apenas algumas das vantagens. As possibilidades são infinitas.

Agora, sempre que existem requisitos para animação, sinto-me confiante para implementar o mesmo. E espero que você também se sinta da mesma maneira depois de ler isso.
Sinta-se à vontade para dar sugestões ou comentários.



Fonte

Leave a Reply

Your email address will not be published. Required fields are marked *