Core Animation adalah framework animasi tingkat rendah Apple yang bekerja pada level CALayer dan menyediakan rendering konten di GPU. Core Animation adalah dasar dari semua animasi di iOS dan macOS: UIKit, AppKit, SceneKit dan SpriteKit dibangun di atasnya. Artikel ini menjelaskan arsitektur CALayer, CABasicAnimation, CATransaction dan teknik praktis.
Poin-poin utama
Core Animation adalah framework grafis Apple yang muncul di Mac OS X 10.5 Leopard (2007) dan diporting ke iOS sejak versi pertama iPhone OS (2007). Core Animation mengelola komposisi, animasi dan rendering layer (CALayer) di GPU. Setiap UIView di iOS memiliki CALayer bawaan (view.layer) yang menjadi saluran untuk semua rendering.
Core Animation bekerja berdasarkan prinsip implicit animation: beberapa perubahan properti CALayer dianimasikan secara otomatis (menganimasikan CABasicAnimation untuk position, bounds, opacity, backgroundColor). Implicit-animasi menggunakan CATransaction secara default dengan durasi 0,25 detik dan kurva easeInOut.
Menurut data Apple WWDC 2024, Core Animation memproses hingga 120 FPS pada perangkat ProMotion, menggunakan Metal untuk rendering GPU. Ukuran layer tipikal di memori adalah 4 byte per piksel (RGBA) + overhead ~100 byte per layer. Disarankan tidak lebih dari 1000 layer per layar untuk 60 FPS yang stabil.
CALayer dasar Core Animation. Setiap CALayer berisi konten bitmap (atau referensi ke tekstur GPU) dan mendefinisikan geometri (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Layer tidak memproses event sentuhan UIView/UIScrollView yang bertanggung jawab untuk itu. Layer membentuk hierarki (layer tree) yang mencerminkan hierarki view.
Core Animation mendukung tiga pohon layer: model layer tree (properti aktual), presentation layer tree (tampilan saat ini selama animasi) dan render tree (data untuk GPU). Presentation layer digunakan untuk membaca nilai antara animasi secara real-time.
CALayer memiliki subkelas khusus: CAShapeLayer (grafik vektor), CAGradientLayer (gradien), CATextLayer (teks), CATiledLayer (gambar besar dibagi menjadi petak), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer adalah yang paling populer untuk animasi kustom berkat dukungan CGPath dan animasi strokeStart/strokeEnd.
CABasicAnimation adalah subkelas CAAnimation yang menganimasikan satu properti CALayer dari nilai awal (fromValue) ke nilai akhir (toValue) atau perubahan relatif (byValue). Animasi ditambahkan ke layer melalui metode layer.add(animation, forKey:) dan dijalankan di render server tanpa partisipasi aplikasi pada setiap frame.
Kunci (keyPath) adalah string yang menunjuk ke properti: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity dll. Core Animation mendukung 60+ keyPath yang dapat dianimasikan. Untuk properti kustom, gunakan CATransaction dan presentation layer.
import QuartzCore
// CABasicAnimation untuk opacity dan 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. Animasi transparansi
let fadeAnim = CABasicAnimation(keyPath: "opacity")
fadeAnim.fromValue = 1.0
fadeAnim.toValue = 0.2
fadeAnim.duration = 2.0
fadeAnim.autoreverses = true
fadeAnim.repeatCount = .infinity
// 2. Animasi pembulatan sudut
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")
}
// Animasi position dengan 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 // memperbarui model layer
}Penting: CABasicAnimation adalah tampilan sementara (presentation layer). Setelah animasi selesai, layer kembali ke nilai awal model layer. Untuk memperbaiki keadaan akhir, atur isRemovedOnCompletion = false, fillMode = .forwards dan perbarui model layer ke nilai akhir.
CATransaction adalah mekanisme untuk mengelompokkan animasi Core Animation dalam satu transaksi. CATransaction.begin() dan CATransaction.commit() menentukan batas transaksi. Di dalam transaksi, parameter bersama dapat diatur: duration, timingFunction, completionBlock, disableActions. CATransaction adalah dasar dari implicit-animasi CALayer.
Implicit animation bekerja ketika properti CALayer diubah di luar blok animasi: layer.opacity = 0.5. Core Animation secara otomatis membuat CABasicAnimation dengan duration dari CATransaction saat ini (default 0,25 dtk). Untuk menonaktifkan implicit-animasi, gunakan CATransaction.setDisableActions(true).
// CATransaction pengelompokan dan penyelesaian
func groupedAnimation() {
CATransaction.begin()
CATransaction.setAnimationDuration(1.5)
CATransaction.setAnimationTimingFunction(
CAMediaTimingFunction(name: .easeOut)
)
CATransaction.setCompletionBlock {
print("All animations completed")
}
// Semua perubahan di dalam transaksi dianimasikan dengan duration 1.5
layer1.opacity = 0.3
layer2.position = CGPoint(x: 200, y: 300)
layer3.backgroundColor = UIColor.systemRed.cgColor
CATransaction.commit()
}
// Menonaktifkan implicit-animasi
func updateWithoutAnimation() {
CATransaction.begin()
CATransaction.setDisableActions(true)
layer.frame = newFrame // tanpa animasi
CATransaction.commit()
}
// Animasi properti 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()
}Core Animation terintegrasi dengan UIKit melalui layer UIView. Contoh di bawah mendemonstrasikan animasi CAShapeLayer bilah kemajuan melingkar dengan animasi panjang busur dan rotasi layer melalui CABasicAnimation.
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 menganimasikan properti strokeEnd dari 0 ke 1, menciptakan efek “pengisian” bilah kemajuan melingkar. CATransaction dengan durasi 0.6 dan easeOut membuat animasi halus. layer.lineCap = .round menambahkan ujung garis membulat untuk tampilan yang lebih rapi.
Pertanyaan yang sering diajukan
Core Animation bekerja pada level CALayer dan dikelola melalui CABasicAnimation, CATransaction. UIView.animate adalah pembungkus tingkat tinggi di atas Core Animation yang secara otomatis membuat CABasicAnimation untuk properti UIView. Core Animation memberikan lebih banyak kontrol: keyPath, timingFunction, fillMode, pengelompokan melalui CATransaction.
Implicit animation adalah animasi otomatis ketika properti CALayer yang dapat dianimasikan diubah di luar blok animasi. Misalnya, layer.opacity = 0.5 membuat CABasicAnimation dengan durasi 0,25 dtk. Implicit-animasi dikelola melalui CATransaction dan dinonaktifkan melalui setDisableActions(true).
Untuk properti kustom, implementasikan action(forKey:) di CALayer dan kembalikan CAAnimation. Atau gunakan CALayer.display() untuk rendering manual dengan animasi melalui CADisplayLink. Untuk properti yang mendukung CABasicAnimation, cukup tentukan keyPath sebagai string.
CALayer lebih ringan dari UIView: tidak memiliki penangan event (touches, gestur), tidak berpartisipasi dalam Auto Layout dan tidak mendukung accessibility. CALayer tipikal memakan ~100 byte dibandingkan ~300+ untuk UIView. Core Animation memproses layer di render server pada GPU tanpa memblokir main thread.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga