CAAnimation เป็นคลาสพื้นฐานนามธรรมของ Core Animation ที่กำหนดอินเทอร์เฟสร่วมสำหรับแอนิเมชันทุกประเภท: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition บทความนี้อธิบายลำดับชั้นของคลาส คุณสมบัติหลัก การจัดกลุ่มแอนิเมชัน และตัวอย่างเชิงปฏิบัติใน Swift
ประเด็นสำคัญ
CAAnimation เป็นคลาสนามธรรมของ Core Animation ที่กำหนดอินเทอร์เฟสร่วมสำหรับแอนิเมชันทั้งหมด โดย implement โปรโตคอล CAMediaTiming (ระยะเวลา การทำซ้ำ การย้อนกลับอัตโนมัติ) และ CAMediaTimingFillMode (พฤติกรรมก่อน/หลังแอนิเมชัน) ไม่สามารถสร้าง instance ของ CAAnimation โดยตรง — ให้ใช้คลาสย่อยตัวใดตัวหนึ่ง: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition หรือ CAAnimation (ผ่าน animationForKeyPath)
CAAnimation แต่ละรายการจะถูกเพิ่มไปยัง CALayer ผ่านเมธอด add(_:forKey:) พารามิเตอร์ forKey คือตัวระบุเฉพาะของแอนิเมชันบนเลเยอร์ หนึ่ง keyPath สามารถมีแอนิเมชันที่ทำงานอยู่ได้เพียงรายการเดียว หากต้องการเปลี่ยนแอนิเมชัน ให้ใช้ removeAnimation(forKey:) ก่อนเพิ่มรายการใหม่
ตามข้อมูลของ Apple CAAnimation คือการเปลี่ยนแปลง "ชั่วคราว" ของเลเยอร์ หลังจากแอนิเมชันเสร็จสิ้น เลเยอร์การนำเสนอจะกลับไปยังค่าเลเยอร์แบบจำลองหากไม่ได้ตั้งค่า fillMode และ isRemovedOnCompletion
Core Animation มีคลาสย่อยหลักของ CAAnimation สี่คลาส แต่ละคลาสสำหรับสถานการณ์แอนิเมชันของตนเอง การทำความเข้าใจลำดับชั้นช่วยเลือกประเภทที่เหมาะสมสำหรับงาน
| คลาส | วัตถุประสงค์ | คุณสมบัติหลัก |
|---|---|---|
| CABasicAnimation | แอนิเมชันคุณสมบัติเดียวจาก A ไป B | fromValue, toValue, byValue, keyPath |
| CAKeyframeAnimation | แอนิเมชันข้ามหลายคีย์เฟรม | values, keyTimes, path, calculationMode |
| CAAnimationGroup | จัดกลุ่มแอนิเมชันหลายรายการ | อาร์เรย์ animations, duration เดียว |
| CATransition | การเปลี่ยนภาพระหว่างสถานะเลเยอร์ | type (fade/push/moveIn/reveal), subtype, startProgress |
CABasicAnimation เป็นคลาสย่อยที่ง่ายและเป็นที่นิยมที่สุด CAKeyframeAnimation ใช้สำหรับวิถีที่ซับซ้อน (เช่น การเคลื่อนที่ตามเส้นโค้ง Bezier) CAAnimationGroup ทำงานแอนิเมชันหลายรายการพร้อมกัน CATransition คือการเปลี่ยนภาพสำเร็จรูประหว่างรูปภาพหรือสถานะเนื้อหา
โปรโตคอล CAMediaTiming เป็นส่วนพื้นฐานของ CAAnimation โดยกำหนดคุณสมบัติเวลาพื้นฐาน: duration, repeatCount, repeatDuration, autoreverses, beginTime (เวลาเริ่มต้นสัมพันธ์กับพ่อแม่), timeOffset (ออฟเซ็ตภายในหนึ่งรอบ), speed (อัตราการเล่น)
คุณสมบัติ fillMode (CAMediaTimingFillMode) กำหนดการแสดงเลเยอร์ก่อน (backwards) และหลัง (forwards) แอนิเมชัน ค่า: removed (ค่าเริ่มต้น — กลับไปยังเลเยอร์แบบจำลอง), forwards (คงอยู่ในสถานะสุดท้าย), backwards (แสดงสถานะเริ่มต้นก่อนเริ่ม), both (รวมทั้งสองพฤติกรรม) fillMode ทำงานเมื่อ isRemovedOnCompletion = false เท่านั้น
CAAnimation สืบทอด CAMediaTiming และสามารถซ้อนอยู่ในแอนิเมชันพ่อแม่ (CAAnimationGroup) ในกรณีนี้ beginTime จะคำนวณสัมพันธ์กับจุดเริ่มต้นของพ่อแม่ และ duration จะถูกจำกัดโดยระยะเวลาของพ่อแม่ Speed = 2.0 จะเพิ่มความเร็วแอนิเมชันเป็นสองเท่า
CAAnimationGroup รวม instance ของ CAAnimation หลายรายการเป็นกลุ่มเดียว แอนิเมชันลูกทั้งหมดเริ่มทำงานพร้อมกันเว้นแต่จะตั้งค่า beginTime สำหรับแต่ละรายการ กลุ่มมี duration ของตัวเอง ซึ่งจำกัดระยะเวลาสูงสุดของแอนิเมชันลูก timingFunction ของกลุ่มถูกใช้เป็นค่าเริ่มต้นหากแอนิเมชันลูกไม่ได้ตั้งค่าของตัวเอง
CAKeyframeAnimation แอนิเมตคุณสมบัติข้ามหลายคีย์เฟรม ซึ่งกำหนดโดยอาร์เรย์ของ values พารามิเตอร์ keyTimes (อาร์เรย์ของ NSNumber จาก 0 ถึง 1) กำหนดประทับเวลาสำหรับแต่ละเฟรม calculationMode ระบุการประมาณค่า: linear, discrete (ไม่มีการประมาณค่า), paced (ความเร็วสม่ำเสมอ), cubic (สปลายน์), cubicPaced
import QuartzCore
// CAAnimationGroup — การรวมแอนิเมชัน
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 — การเคลื่อนที่ตามวิถี
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 ด้วยค่าที่กำหนดเอง
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 // สัมพันธ์กับตำแหน่งปัจจุบัน
layer.add(bounce, forKey: nil)
}CAAnimationGroup ดำเนินการ fade, scale และ rotate พร้อมกันด้วยระยะเวลา 2.0 CAKeyframeAnimation ที่มี path และ calculationMode = .cubicPaced ให้การเคลื่อนที่สม่ำเสมอตามเส้นโค้ง Bezier พร้อมการหมุนอัตโนมัติ (rotationMode = .auto) bounceAnimation ใช้ isAdditive สำหรับออฟเซ็ตสัมพัทธ์
ตัวอย่าง CAAnimation ที่สมบูรณ์สำหรับแอนิเมชันเลเยอร์ที่ซับซ้อนโดยใช้ CATransition สำหรับการสลับเนื้อหาและ CAAnimationGroup สำหรับเอฟเฟกต์การเต้น
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 — การเปลี่ยนภาพระหว่างสถานะ
let transition = CATransition()
transition.type = .fade
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
demoLayer.add(transition, forKey: nil)
// การเปลี่ยนเนื้อหาผ่านธุรกรรม
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 ที่มี type: .fade สร้างการเปลี่ยนภาพที่ราบรื่นระหว่างสองสถานะ backgroundColor CAAnimationGroup รวม scale, opacity และ shadowOpacity สำหรับเอฟเฟกต์การเต้น removeAllAnimations() ยกเลิกแอนิเมชันทั้งหมดและคืนเลเยอร์กลับไปยังค่าเลเยอร์แบบจำลองดั้งเดิม
คำถามที่พบบ่อย
CABasicAnimation แอนิเมตคุณสมบัติจากค่าเริ่มต้น (fromValue) ไปยังค่าสุดท้าย (toValue) ด้วยการประมาณค่าแบบสม่ำเสมอ CAKeyframeAnimation ให้คุณระบุอาร์เรย์ของค่ากลาง (values) และประทับเวลา (keyTimes) สำหรับแอนิเมชันคีย์เฟรมแบบไม่เชิงเส้น รวมถึงการเคลื่อนที่ตามเส้นโค้งผ่าน path
CAAnimationGroup จำเป็นเมื่อแอนิเมชันหลายรายการต้องทำงานพร้อมกันด้วยการซิงค์ที่รับประกัน: ระยะเวลาของกลุ่มจำกัดแอนิเมชันลูกทั้งหมด ใช้ group สำหรับเอฟเฟกต์รวม: การปรับขนาด + การเปลี่ยนความทึบ + การหมุนพร้อมกัน
fillMode กำหนดการแสดงเลเยอร์ก่อน (backwards) และหลัง (forwards) แอนิเมชัน ค่า .forwards จะคงเลเยอร์ไว้ในสถานะสุดท้ายหลังจากแอนิเมชันเสร็จสิ้น (ต้องการ isRemovedOnCompletion = false) .both รวม backwards (สถานะเริ่มต้นก่อนเริ่ม) และ forwards
CAAnimation คือออบเจ็กต์แอนิเมชัน (คำสั่ง) ที่ถูกเพิ่มไปยัง CALayer ผ่าน layer.add(animation, forKey:) แอนิเมชันมีอยู่ในฐานะออบเจ็กต์แยกต่างหาก สามารถนำกลับมาใช้ใหม่ได้ (โดยการคัดลอก) และจัดการผ่าน CAMediaTiming เลเยอร์หนึ่งสามารถมีแอนิเมชันหลายรายการด้วยคีย์ที่แตกต่างกัน
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม