CAShapeLayer — qué es, propiedades y creación de formas

Autor: IT Sectr Publicado: 2026-06-12 Tiempo de lectura: 10 min

CAShapeLayer es una subclase de CALayer diseñada para el renderizado acelerado por hardware de trazados vectoriales en la GPU. A diferencia de CALayer básico, que trabaja con imágenes rasterizadas a través de contents, CAShapeLayer renderiza formas arbitrarias definidas mediante CGPath sin crear un buffer fuera de pantalla separado. Según Apple QuartzCore Documentation, 2025, CAShapeLayer utiliza aceleración hardware para el suavizado de bordes y admite animación de path, strokeStart y strokeEnd. Es una herramienta estándar para crear iconos, indicadores de progreso y máscaras en iOS.

Puntos Clave

  • CAShapeLayer — una subclase de CALayer para renderizar formas vectoriales en GPU a través de CGPath.
  • El renderizado del trazado se realiza por hardware sin crear un buffer rasterizado intermedio — es más rápido que Core Graphics.
  • Propiedades fillColor, strokeColor, lineWidth, lineCap, lineJoin controlan la apariencia de la forma.
  • La animación de path permite transformar suavemente una forma en otra — una capacidad clave para animaciones de UI.
  • strokeStart y strokeEnd se animan para crear un efecto de dibujo del trazado — ideal para indicadores de carga.

Qué es CAShapeLayer?

CAShapeLayer es una capa especializada para renderizar gráficos vectoriales, introducida en iOS 3.0. A diferencia de CALayer, que almacena una imagen rasterizada, CAShapeLayer almacena una descripción matemática de un trazado — CGPath — y lo renderiza directamente en la GPU. Esto permite escalar la forma sin pérdida de calidad y animar sus propiedades sin redescribir el contenido.

Arquitectónicamente, CAShapeLayer hereda todas las capacidades de CALayer: sombras, bordes, transformaciones, máscaras. Pero añade propiedades específicas para trabajar con trazados: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd y fillRule. Cada una de estas propiedades puede ser animada a través de CABasicAnimation.

Según Apple Documentation, CAShapeLayer utiliza aceleración hardware para el renderizado. A diferencia del dibujo mediante Core Graphics en drawRect:, donde la CPU renderiza el trazado en un contexto rasterizado, CAShapeLayer envía comandos directamente a la GPU a través de Metal. El resultado es un mayor rendimiento, especialmente durante la animación.

CAShapeLayer es particularmente útil para elementos de interfaz que cambian de forma en respuesta a acciones del usuario: indicadores de progreso, gráficos, iconos de barra de pestañas, máscaras para animaciones de revelación de contenido.

Cómo renderiza CAShapeLayer un trazado en la GPU

El proceso de renderizado de CAShapeLayer difiere del CALayer básico. En lugar de almacenar un buffer rasterizado con píxeles, CAShapeLayer pasa una descripción de vértices del trazado a la GPU — un conjunto de puntos, curvas Bezier y segmentos de línea. La GPU rasteriza este trazado en una sola pasada, aplicando colores de relleno y trazo en la etapa del shader de fragmentos.

Este enfoque ofrece dos ventajas: escalado sin pérdida de calidad (los gráficos vectoriales permanecen nítidos en cualquier resolución) y animación eficiente — cuando el trazado cambia, la GPU recalcula solo los píxeles modificados, no toda la pantalla.

Propiedades principales de CAShapeLayer

path — la propiedad central de CAShapeLayer, que acepta un CGPath. El trazado puede contener líneas, arcos, curvas Bezier y rectángulos. Se crea mediante UIBezierPath en Swift o CGPath en Core Graphics. Ejemplo: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath crea un rectángulo redondeado.

  • fillColor — el color de relleno del trazado cerrado (CGColor). Si es nil, no hay relleno. Admite animación.
  • strokeColor — el color del trazo del trazado. Se anima junto con lineWidth, creando un efecto de dibujo del trazado.
  • lineWidth — el grosor de la línea de trazo en puntos. Por defecto es 1.0. Se puede animar.
  • lineCap — el estilo del extremo de la línea: .butt (corte recto), .round (redondeado), .square (rectangular con saliente).
  • lineJoin — el estilo de unión de líneas: .miter (ángulo agudo), .round (redondeado), .bevel (biselado).
  • strokeStart y strokeEnd — la fracción del trazado dibujado de 0.0 a 1.0. Animar strokeEnd crea un efecto de revelado gradual.
  • fillRule — la regla de relleno para trazados que se cruzan: .nonZero (por defecto) o .evenOdd.
  • miterLimit — la longitud máxima del pico cuando lineJoin = .miter. Evita esquinas infinitamente largas.

La propiedad lineDashPattern permite crear líneas discontinuas. Acepta un array de números: [6, 3] significa 6 puntos de trazo y 3 puntos de espacio. lineDashPhase establece el desplazamiento del patrón y se puede animar para un efecto de línea discontinua en movimiento.

CAShapeLayer vs CALayer: cuándo elegir cada uno

La elección entre CAShapeLayer y CALayer básico depende del tipo de contenido. Si el elemento es un área rectangular con fondo, borde y sombra — CALayer es suficiente. Si el elemento tiene una forma arbitraria, requiere animación del trazado o escalado sin pérdida de calidad — CAShapeLayer es preferible.

El rendimiento también difiere. CALayer con cornerRadius y masksToBounds crea un buffer fuera de pantalla para recortar contenido, añadiendo 2–5 ms por fotograma. CAShapeLayer no requiere buffer fuera de pantalla — el recorte se realiza a nivel del shader de vértices. Para elementos con máscaras complejas, CAShapeLayer puede ser 2–3 veces más rápido.

  • CALayer: elementos rectangulares, fotos, vídeo, contenido con esquinas redondeadas (cornerRadius), sombras, bordes.
  • CAShapeLayer: iconos, gráficos, barras de progreso, máscaras de forma arbitraria, trazados animados, formas para animaciones de revelación.
  • CATextLayer: texto que requiere renderizado subpixel y almacenamiento en caché de glifos.
  • CAGradientLayer: rellenos degradados — combinado con CAShapeLayer a través de mask para crear formas con degradado.

Combinar CAShapeLayer con otras capas es un patrón común. Por ejemplo, CAGradientLayer usa CAShapeLayer como máscara para crear una forma con relleno degradado. Este enfoque proporciona tanto calidad vectorial como relleno degradado sin pérdida de rendimiento.

Animación de CAShapeLayer: path y stroke

La animación de path es una de las características más potentes de CAShapeLayer. Si ambos trazados (inicial y final) tienen el mismo número de puntos de control y segmentos, Core Animation realiza una interpolación suave entre ellos. El resultado es un efecto de transformación de una forma a otra.

Condición de compatibilidad del trazado: el UIBezierPath inicial y final deben tener la misma estructura — el número de llamadas a moveTo, addLine, addCurve y addQuadCurve debe coincidir. Si la estructura difiere, la animación será instantánea, sin interpolación.

Según Apple WWDC 2024, la combinación de strokeStart y strokeEnd es el patrón de animación de CAShapeLayer más utilizado. Animar strokeEnd de 0.0 a 1.0 crea un efecto de dibujo del trazado de principio a fin. Esto se utiliza en indicadores de carga, animaciones de revelación de gráficos y transiciones personalizadas entre pantallas.

Para crear un efecto pulsante, anime strokeEnd y opacity simultáneamente con diferentes funciones de temporización. Para un efecto de hormigas marchantes, anime lineDashPhase con un lineDashPattern fijo. Ambas técnicas se implementan mediante CABasicAnimation sin participación de la CPU.

Animación como máscara

CAShapeLayer se usa a menudo como máscara para otras capas. Por ejemplo, para animación de revelación de contenido: inicialmente, mask.path es un rectángulo de tamaño cero, y el final es de tamaño completo. Core Animation interpola el trazado y el contenido se revela suavemente.

Este patrón se utiliza en iOS para la animación de expansión de tarjetas, presentación de ventanas modales y transiciones entre controladores de vista. A diferencia de la animación de alpha, la animación de máscara de CAShapeLayer proporciona un efecto de revelado más natural con formas arbitrarias.

Ejemplos de código con CAShapeLayer en Swift

El primer ejemplo — creación de un indicador de progreso circular con animación de strokeEnd. Este es un elemento de interfaz estándar que demuestra las capacidades principales de 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)

El segundo ejemplo — animación de transformación entre un círculo y un cuadrado. Ambos UIBezierPath tienen una estructura compatible:

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

El tercer ejemplo — una máscara CAShapeLayer para animación de revelación de contenido. La máscara se expande desde el centro hacia los bordes:

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
}

Preguntas Frecuentes

En qué se diferencia CAShapeLayer de dibujar en drawRect?

drawRect usa la CPU para renderizar en un contexto rasterizado — esto es lento para animaciones. CAShapeLayer renderiza el trazado en la GPU, ofreciendo 60 FPS durante animaciones de path, strokeEnd y transformaciones. Además, CAShapeLayer no requiere redibujado al cambiar de tamaño — la forma se escala vectorialmente.

Por qué la animación de path no funciona suavemente?

La animación suave del trazado requiere estructura idéntica del UIBezierPath inicial y final. El número de llamadas a moveTo, addLine, addCurve debe coincidir. Use UIBezierPath con el mismo número de segmentos para las formas inicial y final.

Cómo crear una línea discontinua en CAShapeLayer?

Establezca lineDashPattern — un array de números que alternan longitudes de trazo y espacio. Por ejemplo, [8, 4] crea trazos de 8pt con espacios de 4pt. Para un efecto de hormigas marchantes, anime lineDashPhase mediante CABasicAnimation con una función de temporización lineal.

Se puede usar CAShapeLayer como máscara?

Sí, este es uno de los casos de uso principales. Asigne CAShapeLayer a la propiedad mask de cualquier CALayer, incluyendo CAGradientLayer y otras subclases. Animar el trazado de la máscara crea un efecto de revelado suave del contenido a través de una forma arbitraria.

Cómo rellenar una forma con degradado mediante CAShapeLayer?

Cree un CAGradientLayer y establezca su mask = CAShapeLayer con el trazado deseado. El degradado será visible solo dentro del trazado de la máscara. Este patrón combina las ventajas de forma vectorial de CAShapeLayer y el relleno degradado de CAGradientLayer.

Resumen

  • CAShapeLayer — una subclase de CALayer para renderizado acelerado por hardware de trazados vectoriales en la GPU a través de CGPath.
  • Propiedades clave: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, strokeStart, strokeEnd.
  • La animación de path crea transformación de formas — requiere estructura idéntica de los trazados inicial y final.
  • La animación de strokeEnd — un patrón estándar para indicadores de progreso y dibujo de trazados.
  • CAShapeLayer no requiere buffer fuera de pantalla para enmascarar, a diferencia de CALayer con masksToBounds.
  • Se usa como máscara para CAGradientLayer, creando formas con relleno degradado.
  • Para líneas discontinuas, use lineDashPattern con animación de lineDashPhase para un efecto de movimiento.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también