CAShapeLayer — adalah subkelas CALayer yang dirancang untuk rendering perangkat keras kontur vektor di GPU. Berbeda dengan CALayer dasar yang bekerja dengan gambar raster melalui contents, CAShapeLayer merender bentuk arbitrer yang ditentukan melalui CGPath tanpa membuat buffer offscreen terpisah. Menurut Apple QuartzCore Documentation, 2025, CAShapeLayer menggunakan akselerasi perangkat keras untuk menghaluskan tepi dan mendukung animasi path, strokeStart dan strokeEnd. Ini adalah alat standar untuk membuat ikon, indikator kemajuan, dan mask di iOS.
Poin Utama
CAShapeLayer — adalah lapisan khusus untuk rendering grafis vektor, diperkenalkan di iOS 3.0. Berbeda dengan CALayer yang menyimpan gambar raster, CAShapeLayer menyimpan deskripsi matematis kontur — CGPath — dan merendernya langsung di GPU. Ini memungkinkan penskalaan bentuk tanpa kehilangan kualitas dan animasi propertinya tanpa merender ulang konten.
Secara arsitektural, CAShapeLayer mewarisi semua kemampuan CALayer: bayangan, batas, transformasi, mask. Namun menambahkan properti spesifik untuk bekerja dengan kontur: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd dan fillRule. Masing-masing properti ini dapat dianimasikan melalui CABasicAnimation.
Menurut Apple Documentation, CAShapeLayer menggunakan akselerasi perangkat keras saat rendering. Berbeda dengan menggambar melalui Core Graphics di drawRect:, di mana CPU merender kontur dalam konteks raster, CAShapeLayer mengirimkan perintah langsung ke GPU melalui Metal. Hasil — kinerja lebih tinggi, terutama selama animasi.
CAShapeLayer sangat berguna untuk elemen antarmuka yang berubah bentuk sebagai respons terhadap tindakan pengguna: indikator kemajuan, grafik, ikon tab-bar, mask untuk animasi kemunculan konten.
Proses rendering CAShapeLayer berbeda dari CALayer dasar. Alih-alih menyimpan buffer raster dengan piksel, CAShapeLayer mengirimkan deskripsi vertex kontur ke GPU — kumpulan titik, kurva Bezier, dan segmen. GPU meraster kontur ini dalam satu lintasan, menerapkan warna isian dan goresan pada tahap fragment shader.
Pendekatan ini memberikan dua keuntungan: penskalaan tanpa kehilangan kualitas (grafis vektor tetap tajam pada resolusi apa pun) dan animasi yang efisien — saat path berubah, GPU hanya menghitung ulang piksel yang berubah, bukan seluruh layar.
path — properti pusat CAShapeLayer yang menerima CGPath. Kontur dapat berisi garis, busur, kurva Bezier, dan persegi panjang. Dibuat melalui UIBezierPath di Swift atau CGPath di Core Graphics. Contoh: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath membuat persegi panjang membulat.
Properti lineDashPattern memungkinkan pembuatan garis putus-putus. Menerima array angka: [6, 3] berarti 6 titik garis dan 3 titik spasi. lineDashPhase mengatur pergeseran pola dan dapat dianimasikan untuk efek garis putus-putus bergerak.
Pilihan antara CAShapeLayer dan CALayer dasar tergantung pada jenis konten. Jika elemen adalah area persegi panjang dengan latar belakang, batas dan bayangan — CALayer sudah cukup. Jika elemen memiliki bentuk arbitrer, membutuhkan animasi kontur atau penskalaan tanpa kehilangan kualitas — CAShapeLayer lebih disukai.
Kinerja juga berbeda. CALayer dengan cornerRadius dan masksToBounds membuat buffer offscreen untuk memotong konten, yang menambah 2–5 ms per frame. CAShapeLayer tidak memerlukan buffer offscreen — pemotongan dilakukan di tingkat vertex shader. Untuk elemen dengan mask kompleks, CAShapeLayer bisa 2–3 kali lebih cepat.
Menggabungkan CAShapeLayer dengan lapisan lain adalah pola umum. Misalnya, CAGradientLayer menggunakan CAShapeLayer sebagai mask untuk membuat bentuk dengan isian gradien. Pendekatan ini memberikan kualitas vektor dan isian gradien tanpa kehilangan kinerja.
Animasi path — salah satu kemampuan terkuat CAShapeLayer. Jika kedua kontur (awal dan akhir) memiliki jumlah titik kontrol dan segmen yang sama, Core Animation melakukan interpolasi halus di antara keduanya. Hasil — efek perubahan bentuk dari satu bentuk ke bentuk lainnya.
Syarat kompatibilitas path: UIBezierPath awal dan akhir harus memiliki struktur yang sama — jumlah panggilan moveTo, addLine, addCurve dan addQuadCurve harus cocok. Jika struktur berbeda, animasi akan instan, tanpa interpolasi.
Menurut Apple WWDC 2024, kombinasi strokeStart dan strokeEnd adalah pola animasi CAShapeLayer yang paling sering digunakan. Animasi strokeEnd dari 0.0 ke 1.0 menciptakan efek menggambar kontur dari awal hingga akhir. Ini digunakan dalam indikator pemuatan, animasi kemunculan grafik, dan transisi kustom antar layar.
Untuk menciptakan efek denyut, animasikan strokeEnd dan opacity secara bersamaan dengan fungsi timing yang berbeda. Untuk efek garis putus-putus bergerak, animasikan lineDashPhase dengan lineDashPattern tetap. Kedua teknik diimplementasikan melalui CABasicAnimation tanpa partisipasi CPU.
CAShapeLayer sering digunakan sebagai mask untuk lapisan lain. Misalnya, untuk animasi kemunculan konten: pada awalnya mask.path adalah persegi panjang berukuran nol, pada akhir — ukuran penuh. Core Animation melakukan interpolasi path, dan konten terungkap dengan halus.
Pola ini digunakan di iOS untuk animasi pembukaan kartu, kemunculan jendela modal, dan transisi antar view controller. Berbeda dengan animasi alpha, animasi melalui mask CAShapeLayer memberikan efek kemunculan yang lebih alami dengan bentuk arbitrer.
Contoh pertama — membuat indikator kemajuan lingkaran dengan animasi strokeEnd. Ini adalah elemen UI standar yang mendemonstrasikan kemampuan utama CAShapeLayer:
func createProgressIndicator(in view: UIView) -> CAShapeLayer {
let circlePath = UIBezierPath(
arcCenter: CGPoint(x: 50, y: 50),
radius: 40,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true
)
let trackLayer = CAShapeLayer()
trackLayer.path = circlePath.cgPath
trackLayer.strokeColor = UIColor.systemGray5.cgColor
trackLayer.fillColor = nil
trackLayer.lineWidth = 8
view.layer.addSublayer(trackLayer)
let progressLayer = CAShapeLayer()
progressLayer.path = circlePath.cgPath
progressLayer.strokeColor = UIColor.systemBlue.cgColor
progressLayer.fillColor = nil
progressLayer.lineWidth = 8
progressLayer.lineCap = .round
progressLayer.strokeEnd = 0
view.layer.addSublayer(progressLayer)
return progressLayer
}
// Animasi hingga 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Contoh kedua — animasi perubahan bentuk antara lingkaran dan persegi. Kedua UIBezierPath memiliki struktur yang kompatibel:
let morphLayer = CAShapeLayer()
morphLayer.fillColor = UIColor.systemPurple.cgColor
morphLayer.frame = rect
let circlePath = UIBezierPath(roundedRect: rect, cornerRadius: rect.width / 2)
let squarePath = UIBezierPath(roundedRect: rect, cornerRadius: 0)
morphLayer.path = circlePath.cgPath
let morphAnimation = CABasicAnimation(keyPath: "path")
morphAnimation.toValue = squarePath.cgPath
morphAnimation.duration = 0.6
morphAnimation.autoreverses = true
morphAnimation.repeatCount = .infinity
morphLayer.add(morphAnimation, forKey: "morph")
Contoh ketiga — mask dengan CAShapeLayer untuk animasi kemunculan konten. Mask meluas dari pusat ke tepi:
func revealContent(_ view: UIView) {
let maskLayer = CAShapeLayer()
let size = view.bounds.size.width * 1.5
let center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
let initialPath = UIBezierPath(arcCenter: center, radius: 0, startAngle: 0, endAngle: .pi * 2, clockwise: true)
let finalPath = UIBezierPath(arcCenter: center, radius: size, startAngle: 0, endAngle: .pi * 2, clockwise: true)
maskLayer.path = initialPath.cgPath
view.layer.mask = maskLayer
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = finalPath.cgPath
animation.duration = 0.4
animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
maskLayer.add(animation, forKey: "reveal")
maskLayer.path = finalPath.cgPath
}
Pertanyaan Umum
drawRect menggunakan CPU untuk rendering dalam konteks raster — lambat untuk animasi. CAShapeLayer merender kontur di GPU, memberikan 60 FPS pada animasi path, strokeEnd dan transformasi. Selain itu, CAShapeLayer tidak memerlukan rendering ulang saat perubahan ukuran — bentuk diskalakan secara vektor.
Animasi path yang halus memerlukan struktur yang sama dari UIBezierPath awal dan akhir. Jumlah panggilan moveTo, addLine, addCurve harus cocok. Gunakan UIBezierPath dengan jumlah segmen yang sama untuk bentuk awal dan akhir.
Atur lineDashPattern — array angka yang secara bergantian menentukan panjang garis dan spasi. Misalnya, [8, 4] membuat garis 8pt dengan spasi 4pt. Untuk garis putus-putus bergerak, animasikan lineDashPhase melalui CABasicAnimation dengan fungsi timing linear.
Ya, ini adalah salah satu skenario utama. Tetapkan CAShapeLayer ke properti mask dari CALayer mana pun, termasuk CAGradientLayer dan subkelas lainnya. Animasi path mask menciptakan efek kemunculan konten yang halus melalui bentuk arbitrer.
Buat CAGradientLayer dan atur mask-nya = CAShapeLayer dengan path yang diinginkan. Gradien hanya akan terlihat di dalam kontur mask. Pola ini menggabungkan keunggulan bentuk vektor CAShapeLayer dengan isian gradien CAGradientLayer.
Ringkasan
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