Computer >> Hướng Dẫn Máy Tính >  >> Điện Thoại Thông Minh >> iPhone

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

Bài này tập trung vào dùng CA Animations trong iOS để tạo hoạt hình mượt mà.

Trong ngày đầu làm việc với iOS, tôi rất lo lắng khi designer đến nhờ làm hoạt hình cho app họ đang làm.

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

Craaaaap

Tôi từng nghĩ thiết kế hoạt hình dễ – nhưng implement nó, mặt khác, là nhiệm vụ rất khó.

Tôi nhờ Google, StackOverflow, và đồng nghiệp cho implementation.
Quá trình đó tôi phát triển "bệnh sợ hoạt hình" và luôn cố tránh chúng. Nhưng tất cả thay đổi một ngày.

Tìm Thấy CAAnimation

Một lần, tôi phải animate chuỗi hình ảnh trong view. Bước đầu tiên? Tất nhiên, StackOverflow!

Link đầu tiên cho code.

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

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

Có vẻ đơn giản phải không? Nếu đơn giản đến vậy tôi không viết bài này.

Đây là hoạt hình yêu cầu:

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

End Goal

Và như đã rõ, tôi không gần nó chút nào. Tôi bị kẹt. Làm sao customize nhiều như vậy trong hoạt hình và sync tất cả?

Đồng nghiệp bảo thử CAAnimation. Tôi đọc và thử trên sample project. Bất ngờ, nó thật mạnh và dễ dùng.

Core Animation Là Gì?

Core Animation giúp thực thi nhiều hoạt hình với gần như zero CPU usage.
Cho high frame rate và nhiều customizations dùng với rất ít code.

Chi tiết hơn trong docs: https://developer.apple.com/documentation/quartzcore

Tôi implement cơ bản trong vài giờ:

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 }

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

CA Basic Animation

Cho implementation này, tôi dùng CABasicAnimation.

Class CABasicAnimation giúp animate layer property (background color, opacity, position, scale) giữa hai giá trị. Chỉ cần cho start và end value, phần còn lại lo. Hoạt hình bắt đầu ngay ở run loop tiếp theo như mô tả đầy đủ hơn ở đây.

Quay Lại Vấn Đề Của Chúng Ta.

Để implement, tôi lấy hai image view thêm hai ảnh riêng. Sau đó liên tục animate chúng lần lượt dùng CAAnimation.

Source code ở đây.

Nếu xem gif cuối, bạn thấy có gì đó sai. Trước khi hộp quà đầu tiên ra khỏi view, tai nghe lóe lên rồi ảnh mới move lên.

Tại sao?

Vì ngay khi thêm animation vào image view, chúng ta thêm next image vào view đó (line 5 và 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) }

Ở đây chúng ta struggle với issue sync hai ảnh trong hoạt hình. Nhưng luôn có giải pháp với CAAnimation.

CA Transactions

CA Transactions giúp sync nhiều hoạt hình cùng lúc. Đảm bảo tất cả hoạt hình bundled cùng nhau đều bắt đầu cùng lúc.

Cũng, bạn có thể cho completion block cho hoạt hình, sẽ execute khi tất cả hoạt hình trong bundle hoàn thành.

Đọc thêm ở đây.

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

Bắt đầu bằng CATransaction.begin(). Sau đó viết tất cả hoạt hình muốn sync. Cuối cùng gọi CATransaction.commit() bắt đầu hoạt hình trong block.

Xem hoạt hình giờ như nào:

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

CA Transaction

Điều cuối cần làm là thêm Spring effect cho hoạt hình. May mắn CAAnimation cũng có giải pháp.

CA Spring Animation

CA Spring Animation, khi thêm vào layer, cho hiệu ứng giống lò xo, như thể bị kéo về target bởi lò xo.

Càng xa target, gia tốc càng lớn.

Cho phép control thuộc tính vật lý như damping và stiffness của lò xo. – Docs

Đọc thêm tại Apple documentation: https://developer.apple.com/documentation/quartzcore/caspringanimation

Implement vào code hiện tại:

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 }

Làm Chủ Hoạt Hình iOS Với CAAnimation: Vượt Qua Nỗi Sợ Và Mang Lại Chuyển Động Mượt Mà

Voila

Công việc xong.

Tóm lại, vài lợi ích dùng CA Animations:

  • Dễ dùng và implement
  • Nhiều customizations
  • Có thể sync nhiều hoạt hình
  • Gần như zero CPU usage

Chỉ là vài lợi ích. Khả năng vô tận.

Bây giờ, khi requirement hoạt hình đến, tôi tự tin design và implement. Hy vọng bạn cũng cảm thấy vậy sau khi đọc.
Tự do để lại suggestion hoặc feedback.