Core Animation: khái niệm cơ bản, CALayer và hoạt hình trong iOS

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

Core Animation là framework hoạt hình cấp thấp của Apple hoạt động ở cấp độ CALayer và kết xuất nội dung trên GPU. Core Animation là nền tảng của tất cả các hoạt hình trong iOS và macOS: UIKit, AppKit, SceneKit và SpriteKit được xây dựng trên nó. Bài viết này giải thích kiến trúc của CALayer, CABasicAnimation, CATransaction và các kỹ thuật thực tế.

Các điểm chính

  • CALayer — lớp cơ sở của Core Animation để quản lý hiển thị nội dung trên GPU
  • CABasicAnimation — hoạt hình đơn giản của một thuộc tính CALayer từ fromValue đến toValue
  • CATransaction — nhóm các hoạt hình thành một giao dịch duy nhất với thời lượng và hoàn thành chung
  • CAAnimation — lớp cơ sở trừu tượng mà CABasicAnimation, CAKeyframeAnimation và CAAnimationGroup kế thừa
  • Render server — một tiến trình riêng (backboardd) nội suy các khung hình hoạt hình trên GPU

Core Animation là gì?

Core Animation là framework đồ họa của Apple được giới thiệu trong Mac OS X 10.5 Leopard (2007) và được chuyển sang iOS với phiên bản đầu tiên của iPhone OS (2007). Core Animation quản lý việc tổng hợp, hoạt hình và kết xuất các lớp (CALayer) trên GPU. Mỗi UIView trong iOS có một CALayer tích hợp sẵn (view.layer) thông qua đó tất cả việc vẽ diễn ra.

Core Animation hoạt động theo nguyên tắc hoạt hình ngầm: một số thay đổi thuộc tính CALayer tự động hoạt hình (CABasicAnimation cho position, bounds, opacity, backgroundColor). Các hoạt hình ngầm sử dụng CATransaction theo mặc định với thời lượng 0,25 giây và đường cong easeInOut.

Theo Apple WWDC 2024, Core Animation xử lý đến 120 FPS trên các thiết bị ProMotion, sử dụng Metal để kết xuất GPU. Dung lượng bộ nhớ của một lớp điển hình là 4 byte trên mỗi pixel (RGBA) + ~100 byte chi phí trên mỗi lớp. Nên giữ không quá 1000 lớp trên màn hình để đạt 60 FPS ổn định.

Kiến trúc CALayer

CALayer là nền tảng của Core Animation. Mỗi CALayer chứa nội dung bitmap (hoặc tham chiếu kết cấu GPU) và xác định hình học (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Các lớp không xử lý các sự kiện chạm — UIView/UIScrollView xử lý việc đó. Các lớp tạo thành một hệ phân cấp (layer tree) phản ánh hệ phân cấp view.

Core Animation duy trì ba cây lớp: model layer tree (các thuộc tính thực tế), presentation layer tree (hiển thị hiện tại trong quá trình hoạt hình) và render tree (dữ liệu GPU). Lớp trình bày được sử dụng để đọc các giá trị hoạt hình trung gian theo thời gian thực.

Các loại CALayer

CALayer có các lớp con chuyên biệt: CAShapeLayer (đồ họa vector), CAGradientLayer (chuyển sắc), CATextLayer (văn bản), CATiledLayer (hình ảnh lớn được chia thành các ô), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer phổ biến nhất cho hoạt hình tùy chỉnh nhờ hỗ trợ CGPath và hoạt hình strokeStart/strokeEnd.

CABasicAnimation — hoạt hình thuộc tính cơ bản

CABasicAnimation là một lớp con của CAAnimation, hoạt hình một thuộc tính CALayer duy nhất từ giá trị bắt đầu (fromValue) đến giá trị kết thúc (toValue) hoặc bằng một thay đổi tương đối (byValue). Hoạt hình được thêm vào lớp thông qua layer.add(animation, forKey:) và chạy trong máy chủ kết xuất mà không cần sự tham gia của ứng dụng trên mỗi khung hình.

Khóa (keyPath) là một chuỗi chỉ định thuộc tính: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity, v.v. Core Animation hỗ trợ hơn 60 keyPath có thể hoạt hình. Đối với các thuộc tính tùy chỉnh, CATransaction và lớp trình bày được sử dụng.

swift
import QuartzCore

// CABasicAnimation cho opacity và cornerRadius
func animateLayer() {
    let layer = CALayer()
    layer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
    layer.backgroundColor = UIColor.systemBlue.cgColor
    view.layer.addSublayer(layer)

    // 1. Hoạt hình độ trong suốt
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. Hoạt hình bán kính góc
    let cornerAnim = CABasicAnimation(keyPath: "cornerRadius")
    cornerAnim.fromValue = 0
    cornerAnim.toValue = 50
    cornerAnim.duration = 2.0
    cornerAnim.autoreverses = true
    cornerAnim.repeatCount = .infinity

    layer.add(fadeAnim, forKey: "fade")
    layer.add(cornerAnim, forKey: "corner")
}

// Hoạt hình position với ease-in-out
func moveLayer(_ layer: CALayer, to point: CGPoint) {
    let anim = CABasicAnimation(keyPath: "position")
    anim.fromValue = NSValue(cgPoint: layer.position)
    anim.toValue = NSValue(cgPoint: point)
    anim.duration = 0.6
    anim.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
    anim.isRemovedOnCompletion = false
    anim.fillMode = .forwards
    layer.add(anim, forKey: "move")
    layer.position = point // cập nhật model layer
}

Quan trọng: CABasicAnimation là một hiển thị tạm thời (presentation layer). Sau khi hoạt hình hoàn tất, lớp trở về các giá trị model layer. Để cố định trạng thái cuối, đặt isRemovedOnCompletion = false, fillMode = .forwards và cập nhật model layer thành các giá trị cuối.

CATransaction — nhóm hoạt hình

CATransaction là một cơ chế nhóm các hoạt hình Core Animation thành một giao dịch duy nhất. CATransaction.begin() và CATransaction.commit() xác định ranh giới giao dịch. Bên trong một giao dịch, có thể đặt các tham số chung: duration, timingFunction, completionBlock, disableActions. CATransaction là nền tảng của các hoạt hình ngầm CALayer.

Hoạt hình ngầm xảy ra khi một thuộc tính CALayer thay đổi bên ngoài khối hoạt hình: layer.opacity = 0.5. Core Animation tự động tạo một CABasicAnimation với thời lượng từ CATransaction hiện tại (mặc định 0.25 s). Để tắt hoạt hình ngầm, sử dụng CATransaction.setDisableActions(true).

swift
// CATransaction — nhóm và hoàn thành
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // Tất cả các thay đổi trong giao dịch được hoạt hình với thời lượng 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// Tắt hoạt hình ngầm
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // không hoạt hình
    CATransaction.commit()
}

// Hoạt hình các thuộc tính CAShapeLayer
func animateProgress(percentage: CGFloat) {
    CATransaction.begin()
    CATransaction.setAnimationDuration(0.8)
    CATransaction.setCompletionBlock {
        print("Progress updated to (percentage)%")
    }
    progressLayer.strokeEnd = percentage / 100.0
    CATransaction.commit()
}

Ví dụ mã Swift

Core Animation tích hợp với UIKit thông qua lớp UIView. Ví dụ dưới đây minh họa hoạt hình CAShapeLayer — một tiến trình hình tròn với hoạt hình độ dài cung và xoay lớp thông qua CABasicAnimation.

swift
import UIKit
import QuartzCore

class CircularProgressView: UIView {

    private let progressLayer = CAShapeLayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath(
            arcCenter: CGPoint(x: bounds.midX, y: bounds.midY),
            radius: bounds.width / 2 - 10,
            startAngle: -.pi / 2,
            endAngle: 3 * .pi / 2,
            clockwise: true
        )

        progressLayer.path = path.cgPath
        progressLayer.strokeColor = UIColor.systemBlue.cgColor
        progressLayer.lineWidth = 8
        progressLayer.fillColor = nil
        progressLayer.strokeEnd = 0
        progressLayer.lineCap = .round
        layer.addSublayer(progressLayer)
    }

    func setProgress(_ value: CGFloat, animated: Bool = true) {
        if animated {
            CATransaction.begin()
            CATransaction.setAnimationDuration(0.6)
            CATransaction.setAnimationTimingFunction(
                CAMediaTimingFunction(name: .easeOut)
            )
            progressLayer.strokeEnd = min(max(value, 0), 1)
            CATransaction.commit()
        } else {
            progressLayer.strokeEnd = value
        }
    }
}

CAShapeLayer hoạt hình thuộc tính strokeEnd từ 0 đến 1, tạo hiệu ứng “đổ đầy” tiến trình hình tròn. CATransaction với thời lượng 0.6 và easeOut làm cho hoạt hình mượt mà. layer.lineCap = .round thêm các đầu tròn cho đường kẻ để có giao diện sạch hơn.

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

Sự khác biệt giữa Core Animation và UIView.animate là gì?

Core Animation hoạt động ở cấp độ CALayer và được điều khiển qua CABasicAnimation và CATransaction. UIView.animate là một wrapper cấp cao bao quanh Core Animation, tự động tạo CABasicAnimation cho các thuộc tính UIView. Core Animation cung cấp nhiều quyền kiểm soát hơn: keyPath, timingFunction, fillMode, nhóm qua CATransaction.

Hoạt hình ngầm trong Core Animation là gì?

Hoạt hình ngầm là hoạt hình tự động xảy ra khi một thuộc tính có thể hoạt hình của CALayer được thay đổi bên ngoài khối hoạt hình. Ví dụ, layer.opacity = 0.5 tạo CABasicAnimation với thời lượng 0.25 s. Các hoạt hình ngầm được quản lý qua CATransaction và có thể bị tắt bằng setDisableActions(true).

Làm thế nào để hoạt hình một thuộc tính CALayer tùy chỉnh?

Đối với các thuộc tính tùy chỉnh, hãy triển khai action(forKey:) trong CALayer và trả về một CAAnimation. Hoặc sử dụng CALayer.display() để vẽ thủ công với hoạt hình qua CADisplayLink. Đối với các thuộc tính hỗ trợ CABasicAnimation, chỉ cần chỉ định keyPath dưới dạng chuỗi.

Tại sao CALayer hiệu quả hơn UIView cho hoạt hình?

CALayer nhẹ hơn UIView: không có trình xử lý sự kiện (touches, gestures), không tham gia Auto Layout và không hỗ trợ khả năng tiếp cận. Một CALayer điển hình chiếm ~100 byte so với ~300+ của UIView. Core Animation xử lý các lớp trong máy chủ kết xuất trên GPU mà không chặn luồng chính.

Tóm tắt

  • Core Animation — framework cấp thấp của Apple cho hoạt hình CALayer với kết xuất GPU
  • CALayer — lớp cơ sở với hơn 60 thuộc tính có thể hoạt hình, hỗ trợ CAShapeLayer, CAGradientLayer, CATextLayer
  • CABasicAnimation — hoạt hình một thuộc tính với fromValue/toValue, thêm qua layer.add(animation, forKey:)
  • CATransaction — nhóm các hoạt hình với duration, timingFunction, completionBlock chung
  • Hoạt hình ngầm — hoạt hình tự động khi thay đổi thuộc tính CALayer (thời lượng 0.25 s)
  • Presentation layer — trạng thái lớp hiện tại trong quá trình hoạt hình, được sử dụng để đọc các giá trị trung gian
  • Hiệu suất — lên đến 120 FPS trên ProMotion, lên đến 1000 lớp ở 60 FPS, 4 byte/pixel

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