Core Animation: พื้นฐาน CALayer และการอนิเมชันใน iOS

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-03-01 เวลาอ่าน: 8 นาที

Core Animation — กรอบงานอนิเมชันระดับต่ำของ Apple ที่ทำงานบนชั้น CALayer และให้การเรนเดอร์คอนเทนต์บน GPU Core Animation เป็นพื้นฐานของอนิเมชันทั้งหมดใน iOS และ macOS: UIKit, AppKit, SceneKit และ SpriteKit ถูกสร้างขึ้นบนกรอบงานนี้ บทความนี้อธิบายสถาปัตยกรรมของ CALayer, CABasicAnimation, CATransaction และเทคนิคเชิงปฏิบัติ

สิ่งสำคัญ

  • CALayer — คลาสพื้นฐานของ Core Animation สำหรับจัดการการแสดงคอนเทนต์บน GPU
  • CABasicAnimation — อนิเมชันอย่างง่ายของคุณสมบัติหนึ่งของ CALayer จาก fromValue ถึง toValue
  • CATransaction — การจัดกลุ่มอนิเมชันเป็น Transaction เดียวกันด้วย duration และ completion ร่วมกัน
  • CAAnimation — คลาสพื้นฐานนามธรรมที่ CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup สืบทอดมา
  • Render server — โพรเซสแยกต่างหาก (backboardd) ที่ทำการ interpolate เฟรมอนิเมชันบน GPU

Core Animation คืออะไร?

Core Animation — กรอบงานกราฟิกของ Apple ที่เปิดตัวใน Mac OS X 10.5 Leopard (2007) และถูกพอร์ตมายัง iOS ตั้งแต่ iPhone OS เวอร์ชันแรก (2007) Core Animation จัดการการคอมโพสิชัน อนิเมชัน และการเรนเดอร์เลเยอร์ (CALayer) บน GPU ทุก UIView ใน iOS มี CALayer ในตัว (view.layer) ที่ใช้สำหรับการวาดทั้งหมด

Core Animation ทำงานบนหลักการของ implicit animation: การเปลี่ยนแปลงบางอย่างของคุณสมบัติ CALayer จะถูกอนิเมชันโดยอัตโนมัติ Core Animation จะสร้าง CABasicAnimation สำหรับ position, bounds, opacity, backgroundColor โดย implict-อนิเมชันใช้ CATransaction เป็นค่าเริ่มต้นด้วย duration 0.25 วินาทีและเส้นโค้ง easeInOut

ตามข้อมูลของ Apple WWDC 2024, Core Animation สามารถประมวลผลได้ถึง 120 FPS บนอุปกรณ์ที่รองรับ ProMotion โดยใช้ Metal สำหรับการเรนเดอร์ผ่าน GPU ขนาดของเลเยอร์ทั่วไปในหน่วยความจำคือ 4 ไบต์ต่อพิกเซล (RGBA) + overhead ~100 ไบต์ต่อเลเยอร์ แนะนำให้ไม่เกิน 1,000 เลเยอร์ต่อหน้าจอเพื่อ 60 FPS ที่เสถียร

สถาปัตยกรรมของ CALayer

CALayer — พื้นฐานของ Core Animation แต่ละ CALayer ประกอบด้วยคอนเทนต์ bitmap (หรือลิงก์ไปยัง GPU texture) และกำหนดเรขาคณิต (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow) เลเยอร์ไม่จัดการเหตุการณ์การสัมผัส — UIView/UIScrollView รับผิดชอบส่วนนี้ เลเยอร์สร้างลำดับชั้น (layer tree) ที่สะท้อน view hierarchy

Core Animation รองรับสาม layer tree: model layer tree (คุณสมบัติปัจจุบัน), presentation layer tree (การแสดงผลปัจจุบันระหว่างอนิเมชัน) และ render tree (ข้อมูลสำหรับ GPU) Presentation layer ใช้สำหรับอ่านค่ากลางของอนิเมชันแบบเรียลไทม์

ประเภทของ CALayer

CALayer มีคลาสย่อยเฉพาะ: CAShapeLayer (กราฟิกเวกเตอร์), CAGradientLayer (เกรเดียนต์), CATextLayer (ข้อความ), CATiledLayer (ภาพขนาดใหญ่ที่แบ่งเป็นไทล์), CAEAGLLayer/MetalLayer (OpenGL/Metal) CAShapeLayer เป็นที่นิยมที่สุดสำหรับอนิเมชันแบบกำหนดเองเนื่องจากรองรับ CGPath และการอนิเมชัน strokeStart/strokeEnd

CABasicAnimation — อนิเมชันพื้นฐานของคุณสมบัติ

CABasicAnimation — คลาสย่อยของ CAAnimation ที่อนิเมชันหนึ่งคุณสมบัติของ CALayer จากค่าเริ่มต้น (fromValue) ไปยังค่าสุดท้าย (toValue) หรือการเปลี่ยนแปลงสัมพัทธ์ (byValue) อนิเมชันถูกเพิ่มไปยังเลเยอร์ผ่านเมธอด layer.add(animation, forKey:) และทำงานใน render server โดยไม่ต้องให้แอปพลิเคชันทำงานในทุกเฟรม

คีย์ (keyPath) — สตริงที่ระบุคุณสมบัติ: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity ฯลฯ Core Animation รองรับ keyPath ที่อนิเมชันได้ 60+ รายการ สำหรับคุณสมบัติแบบกำหนดเอง ใช้ CATransaction และ presentation layer

swift
import QuartzCore

// CABasicAnimation สำหรับ opacity และ 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. การอนิเมชันความโปร่งใส
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. การอนิเมชันมุมโค้ง
    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")
}

// การอนิเมชัน position ด้วย 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 // อัปเดต model layer
}

สำคัญ: CABasicAnimation เป็นการแสดงผลชั่วคราว (presentation layer) หลังจากอนิเมชันเสร็จสิ้น เลเยอร์จะกลับไปยังค่าเดิมของ model layer เพื่อบันทึกสถานะสุดท้าย ให้ตั้งค่า isRemovedOnCompletion = false, fillMode = .forwards และอัปเดต model layer ไปยังค่าสุดท้าย

CATransaction — การจัดกลุ่มอนิเมชัน

CATransaction — กลไกการจัดกลุ่มอนิเมชัน Core Animation เป็น Transaction เดียวกัน CATransaction.begin() และ CATransaction.commit() กำหนดขอบเขตของ Transaction ภายใน Transaction สามารถกำหนดพารามิเตอร์ร่วม: duration, timingFunction, completionBlock, disableActions CATransaction เป็นพื้นฐานของ implicit-อนิเมชันของ CALayer

Implicit animation ทำงานเมื่อคุณสมบัติของ CALayer ถูกเปลี่ยนแปลงนอกบล็อกอนิเมชัน: layer.opacity = 0.5 Core Animation จะสร้าง CABasicAnimation โดยอัตโนมัติด้วย duration จาก CATransaction ปัจจุบัน (ค่าเริ่มต้น 0.25 วินาที) การปิด implicit-อนิเมชัน ใช้ CATransaction.setDisableActions(true)

swift
// CATransaction — การจัดกลุ่มและ completion
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // การเปลี่ยนแปลงทั้งหมดภายใน Transaction จะถูกอนิเมชันด้วย duration 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// ปิดการใช้งาน implicit-อนิเมชัน
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // ไม่มีการอนิเมชัน
    CATransaction.commit()
}

// การอนิเมชันคุณสมบัติของ 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()
}

ตัวอย่างโค้ดใน Swift

Core Animation ผสานรวมกับ UIKit ผ่านเลเยอร์ของ UIView ตัวอย่างด้านล่างสาธิตการอนิเมชัน CAShapeLayer — วงกลมความคืบหน้าพร้อมอนิเมชันความยาวส่วนโค้งและการหมุนเลเยอร์ผ่าน 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 อนิเมชันคุณสมบัติ strokeEnd จาก 0 ถึง 1 สร้างเอฟเฟกต์ "การเติมเต็ม" ของวงกลมความคืบหน้า CATransaction ด้วย duration 0.6 และ easeOut ทำให้อนิเมชันราบรื่น layer.lineCap = .round เพิ่มปลายเส้นที่โค้งมนเพื่อให้ดูสวยงามยิ่งขึ้น

คำถามที่พบบ่อย

Core Animation กับ UIView.animate ต่างกันอย่างไร?

Core Animation ทำงานบนระดับ CALayer และจัดการผ่าน CABasicAnimation, CATransaction UIView.animate — เป็น wrapper ระดับสูงเหนือ Core Animation ที่สร้าง CABasicAnimation ให้กับคุณสมบัติของ UIView โดยอัตโนมัติ Core Animation ให้การควบคุมมากกว่า: keyPath, timingFunction, fillMode, การจัดกลุ่มผ่าน CATransaction

implicit animation ใน Core Animation คืออะไร?

Implicit animation — อนิเมชันอัตโนมัติเมื่อคุณสมบัติของ CALayer ที่อนิเมชันได้ถูกเปลี่ยนแปลงนอกบล็อกอนิเมชัน ตัวอย่างเช่น layer.opacity = 0.5 จะสร้าง CABasicAnimation ด้วย duration 0.25 วินาที Implicit-อนิเมชันถูกจัดการผ่าน CATransaction และปิดใช้งานได้ด้วย setDisableActions(true)

จะอนิเมชันคุณสมบัติแบบกำหนดเองของ CALayer ได้อย่างไร?

สำหรับคุณสมบัติแบบกำหนดเอง ให้สร้าง action(forKey:) ใน CALayer และคืนค่า CAAnimation หรือใช้ CALayer.display() สำหรับการวาดด้วยตนเองพร้อมอนิเมชันผ่าน CADisplayLink สำหรับคุณสมบัติที่รองรับ CABasicAnimation เพียงระบุ keyPath เป็นสตริง

ทำไม CALayer ถึงมีประสิทธิภาพกว่า UIView สำหรับอนิเมชัน?

CALayer เบากว่า UIView: ไม่มีตัวจัดการเหตุการณ์ (touches, gestures), ไม่เข้าร่วมใน Auto Layout และไม่รองรับ accessibility CALayer ทั่วไปใช้พื้นที่ ~100 ไบต์ เทียบกับ ~300+ ไบต์ของ UIView Core Animation ประมวลผลเลเยอร์ใน render server บน GPU โดยไม่บล็อก main thread

สรุป

  • Core Animation — กรอบงานระดับต่ำของ Apple สำหรับอนิเมชัน CALayer พร้อมการเรนเดอร์บน GPU
  • CALayer — คลาสพื้นฐานที่มีคุณสมบัติที่อนิเมชันได้ 60+ รายการ รองรับ CAShapeLayer, CAGradientLayer, CATextLayer
  • CABasicAnimation — อนิเมชันหนึ่งคุณสมบัติด้วย fromValue/toValue เพิ่มผ่าน layer.add(animation, forKey:)
  • CATransaction — การจัดกลุ่มอนิเมชันด้วย duration, timingFunction, completionBlock ร่วมกัน
  • Implicit animation — อนิเมชันอัตโนมัติเมื่อเปลี่ยนแปลงคุณสมบัติของ CALayer (duration 0.25 วินาที)
  • Presentation layer — สถานะปัจจุบันของเลเยอร์ระหว่างอนิเมชัน ใช้สำหรับอ่านค่ากลาง
  • ประสิทธิภาพ — สูงถึง 120 FPS บน ProMotion, สูงถึง 1,000 เลเยอร์ที่ 60 FPS, 4 ไบต์/พิกเซล

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม