CAShapeLayer — apa itu, properti dan pembuatan bentuk

Penulis: IT Sectr Diterbitkan: 2026-06-12 Waktu membaca: 10 mnt

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 — subkelas CALayer untuk rendering bentuk vektor di GPU melalui CGPath.
  • Rendering kontur dilakukan secara perangkat keras tanpa membuat buffer raster perantara — ini lebih cepat dari Core Graphics.
  • Properti fillColor, strokeColor, lineWidth, lineCap, lineJoin mengontrol tampilan bentuk.
  • Animasi path memungkinkan perubahan bentuk satu ke bentuk lain secara halus — kemampuan kunci untuk animasi UI.
  • strokeStart dan strokeEnd dianimasikan untuk menciptakan efek menggambar kontur — ideal untuk indikator pemuatan.

Apa itu CAShapeLayer?

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.

Bagaimana CAShapeLayer merender kontur di GPU

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.

Properti Utama CAShapeLayer

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.

  • fillColor — warna isian kontur tertutup (CGColor). Jika nil — tanpa isian. Mendukung animasi.
  • strokeColor — warna goresan kontur. Dianimasikan bersama lineWidth, menciptakan efek kontur yang sedang digambar.
  • lineWidth — ketebalan garis goresan dalam titik. Default 1.0. Dapat dianimasikan.
  • lineCap — gaya ujung garis: .butt (potongan lurus), .round (membulat), .square (persegi dengan tonjolan).
  • lineJoin — gaya sambungan garis: .miter (sudut tajam), .round (membulat), .bevel (terpotong).
  • strokeStart dan strokeEnd — proporsi kontur yang digambar dari 0.0 hingga 1.0. Animasi strokeEnd menciptakan efek kemunculan bertahap.
  • fillRule — aturan pengisian kontur yang berpotongan: .nonZero (default) atau .evenOdd.
  • miterLimit — panjang maksimum ujung tajam saat lineJoin = .miter. Mencegah sudut yang sangat panjang.

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.

CAShapeLayer vs CALayer: kapan memilih masing-masing

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.

  • CALayer: elemen persegi panjang, foto, video, konten dengan sudut membulat (cornerRadius), bayangan, batas.
  • CAShapeLayer: ikon, grafik, bilah kemajuan, mask bentuk arbitrer, kontur yang dianimasikan, bentuk untuk animasi kemunculan.
  • CATextLayer: teks yang memerlukan rendering subpiksel dan caching glyph.
  • CAGradientLayer: isian gradien — dikombinasikan dengan CAShapeLayer melalui mask untuk membuat bentuk dengan gradien.

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 CAShapeLayer: path dan stroke

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.

Animasi sebagai mask

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 Kode dengan CAShapeLayer di Swift

Contoh pertama — membuat indikator kemajuan lingkaran dengan animasi strokeEnd. Ini adalah elemen UI standar yang mendemonstrasikan kemampuan utama CAShapeLayer:

swift
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:

swift
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:

swift
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

Apa perbedaan CAShapeLayer dengan menggambar di drawRect?

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.

Mengapa animasi path tidak bekerja dengan halus?

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.

Bagaimana cara membuat garis putus-putus di CAShapeLayer?

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.

Bisakah CAShapeLayer digunakan sebagai mask?

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.

Bagaimana cara mengisi bentuk dengan gradien melalui CAShapeLayer?

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

  • CAShapeLayer — subkelas CALayer untuk rendering perangkat keras kontur vektor di GPU melalui CGPath.
  • Properti kunci: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, strokeStart, strokeEnd.
  • Animasi path menciptakan perubahan bentuk — memerlukan struktur yang sama dari kontur awal dan akhir.
  • Animasi strokeEnd — pola standar untuk indikator kemajuan dan menggambar kontur.
  • CAShapeLayer tidak memerlukan buffer offscreen untuk masking, tidak seperti CALayer dengan masksToBounds.
  • Digunakan sebagai mask untuk CAGradientLayer, menciptakan bentuk dengan isian gradien.
  • Untuk garis putus-putus, gunakan lineDashPattern dengan animasi lineDashPhase untuk efek gerakan.

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.

Diskusikan proyek

Baca juga