CAShapeLayer — що це таке, властивості та створення фігур

Автор: IT Sectr Опубліковано: 2026-06-12 Час читання: 10 хв

CAShapeLayer — це підклас CALayer, призначений для апаратного відтворення векторних контурів на GPU. На відміну від базового CALayer, який працює з растровими зображеннями через contents, CAShapeLayer рендерить довільні фігури, задані через CGPath, без створення окремого offscreen-буфера. За даними Apple QuartzCore Documentation, 2025, CAShapeLayer використовує апаратне прискорення для згладжування країв і підтримує анімацію path, strokeStart та strokeEnd. Це стандартний інструмент для створення іконок, індикаторів прогресу та масок в iOS.

Головне

  • CAShapeLayer — підклас CALayer для рендерингу векторних фігур на GPU через CGPath.
  • Відтворення контуру виконується апаратно без створення проміжного растрового буфера — це швидше за Core Graphics.
  • Властивості fillColor, strokeColor, lineWidth, lineCap, lineJoin керують зовнішнім виглядом фігури.
  • Анімація path дозволяє плавно змінювати одну фігуру на іншу — ключова можливість для UI-анімацій.
  • strokeStart та strokeEnd анімуються для створення ефекту промальовування контуру — ідеально для індикаторів завантаження.

Що таке CAShapeLayer?

CAShapeLayer — це спеціалізований шар для рендерингу векторної графіки, представлений в iOS 3.0. На відміну від CALayer, який зберігає растрове зображення, CAShapeLayer зберігає математичний опис контуру — CGPath — і рендерить його безпосередньо на GPU. Це дозволяє масштабувати фігуру без втрати якості та анімувати її властивості без перемальовування вмісту.

Архітектурно CAShapeLayer успадковує всі можливості CALayer: тіні, межі, трансформації, маски. Але додає специфічні властивості для роботи з контурами: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd та fillRule. Кожна з цих властивостей може бути анімована через CABasicAnimation.

За даними Apple Documentation, CAShapeLayer використовує апаратне прискорення при рендерингу. На відміну від малювання через Core Graphics в drawRect:, де CPU відтворює контур у растровий контекст, CAShapeLayer надсилає команди безпосередньо на GPU через Metal. Результат — вища продуктивність, особливо під час анімації.

CAShapeLayer особливо корисний для елементів інтерфейсу, які змінюють форму у відповідь на дії користувача: індикатори прогресу, графіки, іконки таб-бару, маски для анімації появи контенту.

Як CAShapeLayer рендерить контур на GPU

Процес рендерингу CAShapeLayer відрізняється від базового CALayer. Замість зберігання растрового буфера з пікселями, CAShapeLayer передає GPU вершинний опис контуру — набір точок, кривих Безьє та відрізків. GPU растеризує цей контур за один прохід, застосовуючи колір заливки та обведення на етапі фрагментного шейдера.

Цей підхід дає дві переваги: масштабування без втрати якості (векторна графіка залишається чіткою при будь-якому розширенні) та ефективна анімація — при зміні path GPU перераховує лише змінені пікселі, а не весь екран.

Основні властивості CAShapeLayer

path — центральна властивість CAShapeLayer, що приймає CGPath. Контур може містити лінії, дуги, криві Безьє та прямокутники. Створюється через UIBezierPath в Swift або CGPath в Core Graphics. Приклад: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath створює закруглений прямокутник.

  • fillColor — колір заливки замкненого контуру (CGColor). Якщо nil — заливка відсутня. Підтримується анімація.
  • strokeColor — колір обведення контуру. Анімується разом з lineWidth, створюючи ефект контуру, що малюється.
  • lineWidth — товщина лінії обведення в точках. За замовчуванням 1.0. Може анімуватися.
  • lineCap — стиль закінчення лінії: .butt (прямий зріз), .round (закруглений), .square (прямокутний з виступом).
  • lineJoin — стиль з'єднання ліній: .miter (гострий кут), .round (закруглений), .bevel (зрізаний).
  • strokeStart та strokeEnd — частка промальованого контуру від 0.0 до 1.0. Анімація strokeEnd створює ефект поступової появи.
  • fillRule — правило заливки перехресних контурів: .nonZero (за замовчуванням) або .evenOdd.
  • miterLimit — максимальна довжина гостряка при lineJoin = .miter. Запобігає нескінченно довгим кутам.

Властивість lineDashPattern дозволяє створювати пунктирні лінії. Приймає масив чисел: [6, 3] означає 6 точок штриха та 3 точки пробілу. lineDashPhase задає зміщення патерну та може анімуватися для ефекту рухомого пунктиру.

CAShapeLayer vs CALayer: коли вибирати кожен

Вибір між CAShapeLayer та базовим CALayer залежить від типу контенту. Якщо елемент — прямокутна область з фоном, межею та тінню — достатньо CALayer. Якщо елемент має довільну форму, потребує анімації контуру або масштабування без втрати якості — CAShapeLayer кращий.

Продуктивність також відрізняється. CALayer з cornerRadius та masksToBounds створює offscreen-буфер для обрізки вмісту, що додає 2–5 мс на кадр. CAShapeLayer не потребує offscreen-буфера — обрізка виконується на рівні вершинного шейдера. Для елементів зі складною маскою CAShapeLayer може бути в 2–3 рази швидшим.

  • CALayer: прямокутні елементи, фото, відео, контент з вигнутими кутами (cornerRadius), тіні, межі.
  • CAShapeLayer: іконки, графіки, прогрес-бари, маски довільної форми, анімовані контури, фігури для анімації появи.
  • CATextLayer: текст, що потребує субпіксельного рендерингу та кешування гліфів.
  • CAGradientLayer: градієнтні заливки — комбінується з CAShapeLayer через mask для створення фігур з градієнтом.

Комбінування CAShapeLayer з іншими шарами — поширений патерн. Наприклад, CAGradientLayer використовує CAShapeLayer як маску для створення фігури з градієнтною заливкою. Такий підхід дає і векторну якість, і градієнтне заповнення без втрати продуктивності.

Анімація CAShapeLayer: path та stroke

Анімація path — одна з найпотужніших можливостей CAShapeLayer. Якщо обидва контури (початковий та кінцевий) мають однакову кількість контрольних точок та сегментів, Core Animation виконує плавну інтерполяцію між ними. Результат — ефект морфінгу однієї фігури в іншу.

Умова сумісності path: початковий та кінцевий UIBezierPath повинні мати однакову структуру — кількість викликів moveTo, addLine, addCurve та addQuadCurve має збігатися. Якщо структура відрізняється, анімація буде миттєвою, без інтерполяції.

За даними Apple WWDC 2024, комбінація strokeStart та strokeEnd — найбільш часто використовуваний патерн анімації CAShapeLayer. Анімація strokeEnd від 0.0 до 1.0 створює ефект малювання контуру від початку до кінця. Це використовується в індикаторах завантаження, анімації появи графіків та кастомних переходах між екранами.

Для створення пульсуючого ефекту анімуйте одночасно strokeEnd та opacity з різними timing functions. Для ефекту біжучого пунктиру анімуйте lineDashPhase при фіксованому lineDashPattern. Обидва прийоми реалізуються через CABasicAnimation без участі CPU.

Анімація як маска

CAShapeLayer часто використовується як маска для інших шарів. Наприклад, для анімації появи контенту: на початковому етапі mask.path — це прямокутник нульового розміру, кінцевий — повний розмір. Core Animation інтерполює path, і контент відкривається плавно.

Цей патерн використовується в iOS для анімації розгортання карток, появи модальних вікон та transition між view controllers. На відміну від анімації alpha, анімація через маску CAShapeLayer дає більш природний ефект появи з довільною формою.

Приклади коду з CAShapeLayer в Swift

Перший приклад — створення круглого індикатора прогресу з анімацією strokeEnd. Це стандартний UI-елемент, який демонструє основні можливості 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
}

// Анімувати до 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)

Другий приклад — анімація морфінгу між кругом та квадратом. Обидва UIBezierPath мають сумісну структуру:

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")

Третій приклад — маска з CAShapeLayer для анімації появи контенту. Маска розширюється від центру до країв:

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
}

Поширені запитання

Чим CAShapeLayer відрізняється від малювання в drawRect?

drawRect використовує CPU для відтворення в растровий контекст — це повільно для анімацій. CAShapeLayer рендерить контур на GPU, що дає 60 FPS при анімації path, strokeEnd та трансформацій. Крім того, CAShapeLayer не потребує перемальовування при зміні розмірів — фігура масштабується векторно.

Чому анімація path не працює плавно?

Плавна анімація path потребує однакової структури початкового та кінцевого UIBezierPath. Кількість викликів moveTo, addLine, addCurve має збігатися. Використовуйте UIBezierPath з однаковою кількістю сегментів для початкової та кінцевої фігури.

Як створити пунктирну лінію в CAShapeLayer?

Задайте lineDashPattern — масив чисел, що чергують довжину штриха та пробілу. Наприклад, [8, 4] створює штрихи 8pt з пробілами 4pt. Для біжучого пунктиру анімуйте lineDashPhase через CABasicAnimation з лінійною timing function.

Чи можна використовувати CAShapeLayer як маску?

Так, це один з основних сценаріїв. Призначте CAShapeLayer властивості mask будь-якого CALayer, включаючи CAGradientLayer та інші підкласи. Анімація path маски створює ефект плавної появи контенту через фігуру довільної форми.

Як залити фігуру градієнтом через CAShapeLayer?

Створіть CAGradientLayer та встановіть його mask = CAShapeLayer з потрібним path. Градієнт буде видимий тільки всередині контуру маски. Цей патерн поєднує переваги векторної форми CAShapeLayer та градієнтної заливки CAGradientLayer.

Підсумки

  • CAShapeLayer — підклас CALayer для апаратного рендерингу векторних контурів на GPU через CGPath.
  • Ключові властивості: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, strokeStart, strokeEnd.
  • Анімація path створює морфінг фігур — потребує однакової структури початкового та кінцевого контуру.
  • Анімація strokeEnd — стандартний патерн для індикаторів прогресу та промальовування контурів.
  • CAShapeLayer не потребує offscreen-буфера для маскування, на відміну від CALayer з masksToBounds.
  • Використовується як маска для CAGradientLayer, створюючи фігури з градієнтною заливкою.
  • Для пунктирних ліній використовуйте lineDashPattern з анімацією lineDashPhase для ефекту руху.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також