CAShapeLayer — what it is, properties and creating shapes

Author: IT Sectr Published: 2026-06-12 Reading time: 10 min

CAShapeLayer is a subclass of CALayer designed for hardware-accelerated rendering of vector paths on the GPU. Unlike the basic CALayer, which works with raster images via contents, CAShapeLayer renders arbitrary shapes defined through CGPath without creating a separate offscreen buffer. According to Apple QuartzCore Documentation, 2025, CAShapeLayer uses hardware acceleration for anti-aliasing and supports path, strokeStart and strokeEnd animation. It is a standard tool for creating icons, progress indicators and masks in iOS.

Key Takeaways

  • CAShapeLayer — a subclass of CALayer for rendering vector shapes on the GPU via CGPath.
  • Rendering of the path is done in hardware without creating an intermediate raster buffer — faster than Core Graphics.
  • Properties fillColor, strokeColor, lineWidth, lineCap, lineJoin control the appearance of the shape.
  • Path animation allows smooth morphing of one shape into another — a key capability for UI animations.
  • strokeStart and strokeEnd are animated to create a path drawing effect — ideal for loading indicators.

What is CAShapeLayer?

CAShapeLayer is a specialized layer for rendering vector graphics, introduced in iOS 3.0. Unlike CALayer, which stores a raster image, CAShapeLayer stores a mathematical description of a path — CGPath — and renders it directly on the GPU. This allows the shape to be scaled without quality loss and its properties to be animated without redrawing the contents.

Architecturally, CAShapeLayer inherits all capabilities of CALayer: shadows, borders, transforms, masks. But it adds specific properties for working with paths: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd and fillRule. Each of these properties can be animated via CABasicAnimation.

According to Apple Documentation, CAShapeLayer uses hardware acceleration for rendering. Unlike drawing via Core Graphics in drawRect:, where the CPU renders the path into a raster context, CAShapeLayer sends commands directly to the GPU via Metal. The result is higher performance, especially during animation.

CAShapeLayer is particularly useful for interface elements that change shape in response to user actions: progress indicators, charts, tab bar icons, masks for content reveal animations.

How CAShapeLayer Renders a Path on the GPU

The rendering process of CAShapeLayer differs from the basic CALayer. Instead of storing a raster buffer with pixels, CAShapeLayer passes a vertex description of the path to the GPU — a set of points, Bezier curves and line segments. The GPU rasterizes this path in a single pass, applying fill and stroke colors at the fragment shader stage.

This approach offers two advantages: scaling without quality loss (vector graphics remain sharp at any resolution) and efficient animation — when path changes, the GPU recalculates only the changed pixels, not the entire screen.

Key Properties of CAShapeLayer

path — the central property of CAShapeLayer, accepting a CGPath. The path can contain lines, arcs, Bezier curves and rectangles. It is created via UIBezierPath in Swift or CGPath in Core Graphics. Example: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath creates a rounded rectangle.

  • fillColor — the fill color of the closed path (CGColor). If nil, no fill. Supports animation.
  • strokeColor — the stroke color of the path. Animates together with lineWidth, creating a path-drawing effect.
  • lineWidth — the width of the stroke line in points. Default is 1.0. Can be animated.
  • lineCap — the line end style: .butt (flat cut), .round (rounded), .square (rectangular with protrusion).
  • lineJoin — the line join style: .miter (sharp corner), .round (rounded), .bevel (cut off).
  • strokeStart and strokeEnd — the fraction of the path drawn from 0.0 to 1.0. Animating strokeEnd creates a gradual reveal effect.
  • fillRule — the fill rule for intersecting paths: .nonZero (default) or .evenOdd.
  • miterLimit — the maximum miter length when lineJoin = .miter. Prevents infinitely long corners.

The lineDashPattern property allows creating dashed lines. It accepts an array of numbers: [6, 3] means 6 points of dash and 3 points of gap. lineDashPhase sets the pattern offset and can be animated for a moving dash effect.

CAShapeLayer vs CALayer: When to Choose Each

The choice between CAShapeLayer and the basic CALayer depends on the type of content. If the element is a rectangular area with background, border and shadow — CALayer is sufficient. If the element has an arbitrary shape, requires path animation or lossless scaling — CAShapeLayer is preferable.

Performance also differs. CALayer with cornerRadius and masksToBounds creates an offscreen buffer for content clipping, adding 2–5 ms per frame. CAShapeLayer does not require an offscreen buffer — clipping is performed at the vertex shader level. For elements with complex masks, CAShapeLayer can be 2–3 times faster.

  • CALayer: rectangular elements, photos, video, content with rounded corners (cornerRadius), shadows, borders.
  • CAShapeLayer: icons, charts, progress bars, arbitrary-shaped masks, animated paths, reveal animation shapes.
  • CATextLayer: text requiring subpixel rendering and glyph caching.
  • CAGradientLayer: gradient fills — combined with CAShapeLayer via mask to create shapes with gradients.

Combining CAShapeLayer with other layers is a common pattern. For example, CAGradientLayer uses CAShapeLayer as a mask to create a shape with gradient fill. This approach provides both vector quality and gradient filling without performance loss.

Animating CAShapeLayer: path and stroke

Path animation is one of the most powerful features of CAShapeLayer. If both paths (initial and final) have the same number of control points and segments, Core Animation performs smooth interpolation between them. The result is a morphing effect from one shape to another.

Path compatibility condition: the initial and final UIBezierPath must have the same structure — the number of moveTo, addLine, addCurve and addQuadCurve calls must match. If the structure differs, the animation will be instantaneous, without interpolation.

According to Apple WWDC 2024, the combination of strokeStart and strokeEnd is the most commonly used CAShapeLayer animation pattern. Animating strokeEnd from 0.0 to 1.0 creates a path drawing effect from start to end. This is used in loading indicators, chart reveal animations and custom screen transitions.

To create a pulsing effect, animate strokeEnd and opacity simultaneously with different timing functions. For a marching ants effect, animate lineDashPhase with a fixed lineDashPattern. Both techniques are implemented via CABasicAnimation without CPU involvement.

Animation as a Mask

CAShapeLayer is often used as a mask for other layers. For example, for content reveal animation: initially, mask.path is a zero-size rectangle, and the final is full size. Core Animation interpolates the path, and the content reveals smoothly.

This pattern is used in iOS for card expansion animation, modal window presentation and view controller transitions. Unlike alpha animation, CAShapeLayer mask animation provides a more natural reveal effect with arbitrary shapes.

Code Examples with CAShapeLayer in Swift

The first example — creating a circular progress indicator with strokeEnd animation. This is a standard UI element that demonstrates the core capabilities of 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
}

// Animate to 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)

The second example — morphing animation between a circle and a square. Both UIBezierPath have a compatible structure:

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

The third example — a CAShapeLayer mask for content reveal animation. The mask expands from the center to the edges:

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
}

Frequently Asked Questions

How is CAShapeLayer different from drawing in drawRect?

drawRect uses the CPU to render into a raster context — this is slow for animations. CAShapeLayer renders the path on the GPU, delivering 60 FPS during path, strokeEnd and transform animations. Additionally, CAShapeLayer does not require redrawing when resizing — the shape scales vectorially.

Why doesn't path animation work smoothly?

Smooth path animation requires identical structure of the initial and final UIBezierPath. The number of moveTo, addLine, addCurve calls must match. Use UIBezierPath with the same number of segments for the initial and final shapes.

How to create a dashed line in CAShapeLayer?

Set lineDashPattern — an array of numbers alternating dash and gap lengths. For example, [8, 4] creates 8pt dashes with 4pt gaps. For a marching ants effect, animate lineDashPhase via CABasicAnimation with a linear timing function.

Can CAShapeLayer be used as a mask?

Yes, this is one of the main use cases. Assign CAShapeLayer to the mask property of any CALayer, including CAGradientLayer and other subclasses. Animating the mask path creates a smooth content reveal effect through an arbitrary-shaped figure.

How to fill a shape with a gradient via CAShapeLayer?

Create a CAGradientLayer and set its mask = CAShapeLayer with the desired path. The gradient will be visible only inside the mask path. This pattern combines the vector shape advantages of CAShapeLayer and the gradient fill of CAGradientLayer.

Summary

  • CAShapeLayer — a subclass of CALayer for hardware-accelerated rendering of vector paths on the GPU via CGPath.
  • Key properties: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, strokeStart, strokeEnd.
  • path animation creates shape morphing — requires identical structure of initial and final paths.
  • strokeEnd animation — a standard pattern for progress indicators and path drawing.
  • CAShapeLayer does not require an offscreen buffer for masking, unlike CALayer with masksToBounds.
  • Used as a mask for CAGradientLayer, creating shapes with gradient fill.
  • For dashed lines, use lineDashPattern with lineDashPhase animation for a motion effect.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also