CAAnimation — Các khái niệm chính, CAAnimationGroup và hoạt ảnh lớp

Tác giả: IT Sectr Đã đăng: 2026-03-01 Thời gian đọc: 8 phút

CAAnimation là lớp cơ sở trừu tượng của Core Animation, định nghĩa giao diện chung cho tất cả các loại hoạt ảnh: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition. Bài viết giải thích hệ thống phân cấp lớp, các thuộc tính chính, nhóm hoạt ảnh và các ví dụ thực tế bằng Swift.

Những điểm chính

  • CAAnimation — lớp cơ sở trừu tượng của Core Animation, từ đó CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition kế thừa
  • CAAnimationGroup — thực thi song song nhiều hoạt ảnh với duration và timingFunction dùng chung
  • CAKeyframeAnimation — hoạt ảnh theo khung hình chính với mảng giá trị và dấu thời gian
  • CAMediaTiming — giao thức quản lý thời gian: duration, repeatCount, autoreverses, timeOffset
  • CATransition — chuyển tiếp được xác định trước giữa các trạng thái lớp (fade, push, moveIn, reveal)

CAAnimation là gì?

CAAnimation là một lớp trừu tượng của Core Animation, định nghĩa giao diện chung cho tất cả các hoạt ảnh. Nó triển khai giao thức CAMediaTiming (thời lượng, lặp lại, tự động đảo ngược) và CAMediaTimingFillMode (hành vi trước/sau hoạt ảnh). CAAnimation không thể được khởi tạo trực tiếp — hãy sử dụng một trong các lớp con của nó: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition hoặc CAAnimation (thông qua animationForKeyPath).

Mỗi CAAnimation được thêm vào CALayer thông qua phương thức add(_:forKey:). Tham số forKey là mã định danh duy nhất của hoạt ảnh trên lớp. Một keyPath chỉ có thể có một hoạt ảnh đang hoạt động. Để thay thế hoạt ảnh, hãy sử dụng removeAnimation(forKey:) trước khi thêm hoạt ảnh mới.

Theo Apple, CAAnimation là một thay đổi "tạm thời" của lớp. Sau khi hoạt ảnh hoàn thành, lớp trình bày trở về giá trị của lớp mô hình nếu fillMode và isRemovedOnCompletion không được đặt.

Hệ thống phân cấp lớp CAAnimation

Core Animation cung cấp bốn lớp con chính của CAAnimation, mỗi lớp dành cho một kịch bản hoạt ảnh riêng. Hiểu được hệ thống phân cấp giúp chọn đúng loại cho công việc.

LớpMục đíchTính năng chính
CABasicAnimationHoạt ảnh một thuộc tính từ A đến BfromValue, toValue, byValue, keyPath
CAKeyframeAnimationHoạt ảnh qua nhiều khung hình chínhvalues, keyTimes, path, calculationMode
CAAnimationGroupNhóm nhiều hoạt ảnhmảng animations, duration đơn nhất
CATransitionChuyển tiếp giữa các trạng thái lớptype (fade/push/moveIn/reveal), subtype, startProgress

CABasicAnimation là lớp con đơn giản nhất và phổ biến nhất. CAKeyframeAnimation được sử dụng cho các quỹ đạo phức tạp (ví dụ: chuyển động dọc theo đường cong Bezier). CAAnimationGroup chạy nhiều hoạt ảnh song song. CATransition là chuyển tiếp có sẵn giữa các hình ảnh hoặc trạng thái nội dung.

CAMediaTiming — quản lý thời gian

Giao thức CAMediaTiming là một phần cơ bản của CAAnimation. Nó định nghĩa các thuộc tính thời gian cơ bản: duration, repeatCount, repeatDuration, autoreverses, beginTime (thời gian bắt đầu so với cha), timeOffset (độ lệch trong một chu kỳ), speed (tốc độ phát lại).

Thuộc tính fillMode (CAMediaTimingFillMode) xác định hiển thị lớp trước (backwards) và sau (forwards) hoạt ảnh. Các giá trị: removed (mặc định — trở về lớp mô hình), forwards (giữ nguyên trạng thái cuối), backwards (hiển thị trạng thái ban đầu trước khi bắt đầu), both (kết hợp cả hai hành vi). fillMode chỉ hoạt động khi isRemovedOnCompletion = false.

CAAnimation kế thừa CAMediaTiming và có thể được lồng trong hoạt ảnh cha (CAAnimationGroup). Trong trường hợp này, beginTime được tính so với thời điểm bắt đầu của cha và duration bị giới hạn bởi thời lượng của cha. Speed = 2.0 tăng gấp đôi tốc độ hoạt ảnh.

CAAnimationGroup và CAKeyframeAnimation

CAAnimationGroup kết hợp nhiều phiên bản CAAnimation thành một nhóm duy nhất. Tất cả các hoạt ảnh con bắt đầu song song trừ khi beginTime được đặt cho mỗi hoạt ảnh. Nhóm có duration riêng, giới hạn thời lượng tối đa của các hoạt ảnh con. timingFunction của nhóm được sử dụng làm giá trị mặc định nếu hoạt ảnh con không đặt giá trị riêng.

CAKeyframeAnimation tạo hoạt ảnh cho một thuộc tính qua nhiều khung hình chính, được xác định bởi một mảng values. Tham số keyTimes (mảng NSNumber từ 0 đến 1) xác định dấu thời gian cho mỗi khung hình. calculationMode chỉ định phép nội suy: linear, discrete (không nội suy), paced (tốc độ đồng đều), cubic (spline), cubicPaced.

swift
import QuartzCore

// CAAnimationGroup — kết hợp hoạt ảnh
func complexLayerAnimation(_ layer: CALayer) {
    let fade = CABasicAnimation(keyPath: "opacity")
    fade.fromValue = 1.0
    fade.toValue = 0.3

    let scale = CABasicAnimation(keyPath: "transform.scale")
    scale.fromValue = 1.0
    scale.toValue = 1.5

    let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
    rotate.fromValue = 0
    rotate.toValue = Double.pi * 2

    let group = CAAnimationGroup()
    group.animations = [fade, scale, rotate]
    group.duration = 2.0
    group.repeatCount = .infinity
    group.autoreverses = true

    layer.add(group, forKey: "pulse")
}

// CAKeyframeAnimation — chuyển động theo quỹ đạo
func animateAlongPath(_ layer: CALayer) {
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 0, y: 0))
    path.addCurve(
        to: CGPoint(x: 200, y: 300),
        controlPoint1: CGPoint(x: 100, y: 0),
        controlPoint2: CGPoint(x: 100, y: 300)
    )

    let anim = CAKeyframeAnimation(keyPath: "position")
    anim.path = path.cgPath
    anim.duration = 1.5
    anim.calculationMode = .cubicPaced
    anim.rotationMode = .auto
    anim.fillMode = .forwards
    anim.isRemovedOnCompletion = false

    layer.add(anim, forKey: "pathAnim")
    layer.position = CGPoint(x: 200, y: 300)
}

// CAKeyframeAnimation với giá trị tùy chỉnh
func bounceAnimation(_ layer: CALayer) {
    let bounce = CAKeyframeAnimation(keyPath: "position.y")
    bounce.values = [0, -50, 0, -25, 0, -10, 0]
    bounce.keyTimes = [0, 0.15, 0.3, 0.45, 0.6, 0.8, 1.0]
    bounce.duration = 0.8
    bounce.timingFunction = CAMediaTimingFunction(name: .easeOut)
    bounce.isAdditive = true // so với vị trí hiện tại
    layer.add(bounce, forKey: nil)
}

CAAnimationGroup thực thi fade, scale và rotate song song với thời lượng 2.0. CAKeyframeAnimation với pathcalculationMode = .cubicPaced cung cấp chuyển động đồng đều dọc theo đường cong Bezier với xoay tự động (rotationMode = .auto). bounceAnimation sử dụng isAdditive cho độ lệch tương đối.

Ví dụ mã Swift

Một ví dụ hoàn chỉnh về CAAnimation cho hoạt ảnh lớp phức tạp sử dụng CATransition để chuyển đổi nội dung và CAAnimationGroup cho hiệu ứng xung.

swift
import UIKit
import QuartzCore

class AnimationDemoView: UIView {

    private let demoLayer = CALayer()
    private var currentColor: CGColor = UIColor.systemBlue.cgColor

    override func layoutSubviews() {
        super.layoutSubviews()
        demoLayer.frame = CGRect(x: bounds.midX - 40, y: bounds.midY - 40,
                                 width: 80, height: 80)
        demoLayer.backgroundColor = currentColor
        demoLayer.cornerRadius = 12
        layer.addSublayer(demoLayer)
    }

    func animateTransition() {
        // CATransition — chuyển tiếp giữa các trạng thái
        let transition = CATransition()
        transition.type = .fade
        transition.duration = 0.5
        transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        demoLayer.add(transition, forKey: nil)

        // Thay đổi nội dung qua giao dịch
        currentColor = currentColor == UIColor.systemBlue.cgColor
            ? UIColor.systemRed.cgColor
            : UIColor.systemBlue.cgColor
        demoLayer.backgroundColor = currentColor
    }

    func startPulse() {
        let scaleUp = CABasicAnimation(keyPath: "transform.scale")
        scaleUp.fromValue = 1.0
        scaleUp.toValue = 1.3

        let fadeOut = CABasicAnimation(keyPath: "opacity")
        fadeOut.fromValue = 1.0
        fadeOut.toValue = 0.6

        let glow = CABasicAnimation(keyPath: "shadowOpacity")
        glow.fromValue = 0.0
        glow.toValue = 0.8

        let group = CAAnimationGroup()
        group.animations = [scaleUp, fadeOut, glow]
        group.duration = 1.2
        group.autoreverses = true
        group.repeatCount = .infinity
        group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)

        demoLayer.add(group, forKey: "pulse")
    }

    func stopAnimations() {
        demoLayer.removeAllAnimations()
        demoLayer.transform = CATransform3DIdentity
        demoLayer.opacity = 1.0
        demoLayer.shadowOpacity = 0.0
    }
}

CATransition với type: .fade tạo chuyển tiếp mượt mà giữa hai trạng thái backgroundColor. CAAnimationGroup kết hợp scale, opacity và shadowOpacity để tạo hiệu ứng xung. removeAllAnimations() hủy tất cả hoạt ảnh và đưa lớp trở về giá trị lớp mô hình ban đầu.

Các câu hỏi thường gặp

Sự khác biệt giữa CABasicAnimation và CAKeyframeAnimation là gì?

CABasicAnimation tạo hoạt ảnh cho một thuộc tính từ giá trị ban đầu (fromValue) đến giá trị cuối (toValue) với phép nội suy đồng đều. CAKeyframeAnimation cho phép bạn chỉ định một mảng các giá trị trung gian (values) và dấu thời gian (keyTimes) cho hoạt ảnh khung hình chính phi tuyến tính, bao gồm chuyển động dựa trên đường cong thông qua path.

Khi nào nên sử dụng CAAnimationGroup?

CAAnimationGroup cần thiết khi nhiều hoạt ảnh phải chạy song song với sự đồng bộ được đảm bảo: thời lượng của nhóm giới hạn tất cả các hoạt ảnh con. Sử dụng group cho các hiệu ứng kết hợp: thay đổi tỷ lệ + thay đổi độ mờ + xoay đồng thời.

fillMode trong CAAnimation là gì?

fillMode xác định hiển thị lớp trước (backwards) và sau (forwards) hoạt ảnh. Giá trị .forwards giữ lớp ở trạng thái cuối sau khi hoạt ảnh hoàn thành (yêu cầu isRemovedOnCompletion = false). .both kết hợp backwards (trạng thái ban đầu trước khi bắt đầu) và forwards.

CAAnimation khác với hoạt ảnh CALayer như thế nào?

CAAnimation là một đối tượng hoạt ảnh (chỉ thị) được thêm vào CALayer thông qua layer.add(animation, forKey:). Hoạt ảnh tồn tại như một đối tượng riêng biệt, có thể được tái sử dụng (bằng cách sao chép) và được quản lý thông qua CAMediaTiming. Một lớp có thể có nhiều hoạt ảnh với các khóa khác nhau.

Tổng kết

  • CAAnimation — lớp cơ sở trừu tượng của Core Animation triển khai CAMediaTiming và CAMediaTimingFillMode
  • Hệ thống phân cấp lớp — CABasicAnimation (một thuộc tính), CAKeyframeAnimation (nhiều khung hình), CAAnimationGroup (nhóm), CATransition (chuyển tiếp)
  • CAMediaTiming — giao thức với duration, repeatCount, autoreverses, beginTime, timeOffset, speed, fillMode
  • CAAnimationGroup — thực thi hoạt ảnh song song với một duration và timingFunction duy nhất
  • CAKeyframeAnimation — hoạt ảnh qua values/keyTimes hoặc path (đường cong Bezier) với calculationMode
  • CATransition — các loại được xác định trước: fade, push, moveIn, reveal với cấu hình subtype
  • Quản lý — layer.add(animation, forKey:), removeAnimation(forKey:), removeAllAnimations()

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm