CAShapeLayerは、GPU上でベクターパスをハードウェア加速レンダリングするために設計されたCALayerのサブクラスです。contentsを介してラスターイメージを扱う基本的なCALayerとは異なり、CAShapeLayerはオフスクリーンバッファを作成せずにCGPathを通じて定義された任意の図形をレンダリングします。Apple QuartzCore Documentation, 2025によると、CAShapeLayerはエッジのアンチエイリアシングにハードウェア加速を使用し、path、strokeStart、strokeEndのアニメーションをサポートしています。iOSでアイコン、進捗インジケータ、マスクを作成するための標準的なツールです。
重要なポイント
CAShapeLayerは、iOS 3.0で導入されたベクターグラフィックスをレンダリングするための特殊なレイヤーです。ラスターイメージを保存するCALayerとは異なり、CAShapeLayerはパス(CGPath)の数学的記述を保存し、GPU上で直接レンダリングします。これにより、品質を損なうことなく図形を拡大縮小でき、内容を再描画せずにプロパティをアニメーションできます。
アーキテクチャ的には、CAShapeLayerはCALayerのすべての機能(シャドウ、ボーダー、トランスフォーム、マスク)を継承しています。さらに、パスを扱うための固有のプロパティを追加します:path、fillColor、strokeColor、lineWidth、lineCap、lineJoin、miterLimit、strokeStart、strokeEnd、fillRule。これらの各プロパティはCABasicAnimationを介してアニメーションできます。
Apple Documentationによると、CAShapeLayerはレンダリングにハードウェア加速を使用します。drawRect:でのCore Graphicsを介した描画(CPUがパスをラスターコンテキストにレンダリングする)とは異なり、CAShapeLayerはMetalを介してGPUに直接コマンドを送信します。結果として、特にアニメーション中により高いパフォーマンスが得られます。
CAShapeLayerは、ユーザーの操作に応じて形状が変化するインターフェース要素(進捗インジケータ、グラフ、タブバーアイコン、コンテンツ表示アニメーション用のマスク)に特に役立ちます。
CAShapeLayerのレンダリングプロセスは基本的なCALayerとは異なります。ピクセルを含むラスターバッファを保存する代わりに、CAShapeLayerはパスの頂点記述(点、ベジェ曲線、線分のセット)をGPUに渡します。GPUはこのパスを1パスでラスタライズし、フラグメントシェーダーステージで塗りつぶし色とストローク色を適用します。
このアプローチには2つの利点があります:品質を損なわない拡大縮小(ベクターグラフィックスは任意の解像度でシャープさを維持)と効率的なアニメーション(パスが変更されると、GPUは画面全体ではなく変更されたピクセルのみを再計算します)。
path — CAShapeLayerの中心的なプロパティで、CGPathを受け取ります。パスには線、円弧、ベジェ曲線、長方形を含めることができます。SwiftではUIBezierPath、Core GraphicsではCGPathを介して作成されます。例:UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPathは角丸長方形を作成します。
lineDashPatternプロパティは破線を作成できます。数値の配列を受け取ります:[6, 3]は6ポイントのダッシュと3ポイントのギャップを意味します。lineDashPhaseはパターンオフセットを設定し、ダッシュ移動効果のためにアニメーションできます。
CAShapeLayerと基本的なCALayerの選択は、コンテンツの種類によって異なります。要素が背景、ボーダー、シャドウを持つ長方形領域の場合、CALayerで十分です。要素が任意の形状を持ち、パスアニメーションや品質を損なわない拡大縮小が必要な場合、CAShapeLayerが適しています。
パフォーマンスも異なります。cornerRadiusとmasksToBoundsを持つCALayerは、コンテンツクリッピングのためにオフスクリーンバッファを作成し、フレームあたり2〜5ミリ秒追加します。CAShapeLayerはオフスクリーンバッファを必要としません — クリッピングは頂点シェーダーレベルで実行されます。複雑なマスクを持つ要素の場合、CAShapeLayerは2〜3倍高速になります。
CAShapeLayerを他のレイヤーと組み合わせるのは一般的なパターンです。例えば、CAGradientLayerはCAShapeLayerをマスクとして使用し、グラデーション塗りつぶしの図形を作成します。このアプローチは、パフォーマンスを損なうことなくベクター品質とグラデーション塗りつぶしの両方を提供します。
パスアニメーションはCAShapeLayerの最も強力な機能の1つです。両方のパス(初期と最終)が同じ数の制御点とセグメントを持つ場合、Core Animationはそれらの間で滑らかな補間を実行します。結果として、ある図形から別の図形へのモーフィング効果が得られます。
パスの互換性条件:初期と最終のUIBezierPathは同じ構造を持つ必要があります — moveTo、addLine、addCurve、addQuadCurveの呼び出し数が一致する必要があります。構造が異なる場合、アニメーションは補間なしで瞬時に行われます。
Apple WWDC 2024によると、strokeStartとstrokeEndの組み合わせは最も一般的に使用されるCAShapeLayerアニメーションパターンです。strokeEndを0.0から1.0にアニメーションすると、パスの最初から最後までの描画効果が生まれます。これは読み込みインジケータ、グラフ表示アニメーション、カスタム画面遷移で使用されます。
パルス効果を作成するには、異なるタイミング関数でstrokeEndとopacityを同時にアニメーションします。動く破線効果の場合は、固定のlineDashPatternでlineDashPhaseをアニメーションします。両方のテクニックは、CPUの関与なしにCABasicAnimationを介して実装されます。
CAShapeLayerは他のレイヤーのマスクとしてよく使用されます。例えば、コンテンツ表示アニメーションの場合:初期状態ではmask.pathはサイズゼロの長方形で、最終状態ではフルサイズです。Core Animationがパスを補間し、コンテンツが滑らかに表示されます。
このパターンは、iOSでのカード展開アニメーション、モーダルウィンドウの表示、ビューコントローラーのトランジションに使用されます。アルファアニメーションとは異なり、CAShapeLayerマスクアニメーションは任意の形状でより自然な表示効果を提供します。
最初の例 — strokeEndアニメーションを使用した円形進捗インジケータの作成。これはCAShapeLayerの主要機能を示す標準的なUI要素です:
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)
2番目の例 — 円と正方形の間のモーフィングアニメーション。両方のUIBezierPathは互換性のある構造を持っています:
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")
3番目の例 — コンテンツ表示アニメーション用のCAShapeLayerマスク。マスクは中心から端に向かって拡大します:
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
}
よくある質問
drawRectはラスターコンテキストにレンダリングするためにCPUを使用します — これはアニメーションには低速です。CAShapeLayerはGPU上でパスをレンダリングし、path、strokeEnd、トランスフォームのアニメーション中に60 FPSを提供します。さらに、CAShapeLayerはサイズ変更時に再描画を必要としません — 図形はベクターとして拡大縮小されます。
スムーズなパスアニメーションには、初期と最終のUIBezierPathが同一の構造を持つ必要があります。moveTo、addLine、addCurveの呼び出し数が一致する必要があります。初期と最終の図形には同じセグメント数のUIBezierPathを使用してください。
lineDashPatternを設定します — ダッシュとギャップの長さを交互に指定する数値の配列。例えば、[8, 4]は8ptのダッシュと4ptのギャップを作成します。動く破線効果の場合は、線形タイミング関数でCABasicAnimationを介してlineDashPhaseをアニメーションします。
はい、これは主要な使用例の1つです。CAGradientLayerや他のサブクラスを含む任意のCALayerのmaskプロパティにCAShapeLayerを割り当てます。マスクパスをアニメーションすると、任意の形状を通じたコンテンツのスムーズな表示効果が生まれます。
CAGradientLayerを作成し、そのmask = 目的のパスを持つCAShapeLayerに設定します。グラデーションはマスクパスの内側にのみ表示されます。このパターンはCAShapeLayerのベクター形状の利点とCAGradientLayerのグラデーション塗りつぶしを組み合わせます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。