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 دستورات را مستقیماً از طریق Metal به GPU ارسال می‌کند. نتیجه — عملکرد بالاتر، به ویژه در هنگام انیمیشن.

CAShapeLayer به ویژه برای عناصر رابط کاربری که در پاسخ به اقدامات کاربر شکل خود را تغییر می‌دهند مفید است: نشانگرهای پیشرفت، نمودارها، آیکون‌های نوار تب، ماسک‌های انیمیشن ظاهر شدن محتوا.

چگونه CAShapeLayer مسیر را روی GPU رندر می‌کند

فرآیند رندر CAShapeLayer با CALayer پایه متفاوت است. به جای ذخیره بافر شطرنجی با پیکسل‌ها، CAShapeLayer توصیف رأس مسیر را به GPU ارسال می‌کند — مجموعه‌ای از نقاط، منحنی‌های Bezier و قطعات. GPU این مسیر را در یک pass رستر می‌کند و رنگ پر کردن و ضربه را در مرحله shader قطعه اعمال می‌کند.

این رویکرد دو مزیت دارد: مقیاس‌پذیری بدون افت کیفیت (گرافیک برداری در هر وضوحی واضح می‌ماند) و انیمیشن کارآمد — هنگام تغییر path، GPU فقط پیکسل‌های تغییر یافته را دوباره محاسبه می‌کند، نه کل صفحه را.

ویژگی‌های اصلی CAShapeLayer

path — ویژگی مرکزی CAShapeLayer که CGPath را می‌پذیرد. مسیر می‌تواند شامل خطوط، کمان‌ها، منحنی‌های Bezier و مستطیل‌ها باشد. از طریق 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 در مقابل CALayer: چه زمانی کدام را انتخاب کنیم

انتخاب بین CAShapeLayer و CALayer پایه به نوع محتوا بستگی دارد. اگر عنصر یک ناحیه مستطیلی با پس‌زمینه، مرز و سایه است — CALayer کافی است. اگر عنصر شکل دلخواه دارد، نیاز به انیمیشن مسیر یا مقیاس‌پذیری بدون افت کیفیت دارد — CAShapeLayer ارجح است.

عملکرد نیز متفاوت است. CALayer با cornerRadius و masksToBounds یک بافر offscreen برای برش محتوا ایجاد می‌کند که 2–5 میلی‌ثانیه به هر فریم اضافه می‌کند. CAShapeLayer به بافر offscreen نیاز ندارد — برش در سطح shader رأس انجام می‌شود. برای عناصر با ماسک پیچیده، CAShapeLayer می‌تواند 2–3 برابر سریع‌تر باشد.

  • CALayer: عناصر مستطیلی، عکس‌ها، ویدئو، محتوای با گوشه‌های گرد (cornerRadius)، سایه‌ها، مرزها.
  • CAShapeLayer: آیکون‌ها، نمودارها، نوارهای پیشرفت، ماسک‌های با شکل دلخواه، مسیرهای انیمیشنی، اشکال برای انیمیشن ظاهر شدن.
  • CATextLayer: متنی که نیاز به رندر زیرپیکسلی و کش گلیف دارد.
  • CAGradientLayer: پرکننده‌های گرادیانی — از طریق mask با CAShapeLayer ترکیب می‌شود برای ایجاد اشکال با گرادیان.

ترکیب 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 را همزمان با توابع زمانی مختلف انیمیشن دهید. برای اثر خط نقطه‌چین متحرک، lineDashPhase را با lineDashPattern ثابت انیمیشن دهید. هر دو تکنیک از طریق CABasicAnimation بدون مشارکت CPU پیاده‌سازی می‌شوند.

انیمیشن به عنوان ماسک

CAShapeLayer اغلب به عنوان mask برای لایه‌های دیگر استفاده می‌شود. به عنوان مثال، برای انیمیشن ظاهر شدن محتوا: در ابتدا mask.path یک مستطیل با اندازه صفر است، در پایان — اندازه کامل. Core Animation path را درون‌یابی می‌کند و محتوا به آرامی نمایان می‌شود.

این الگو در iOS برای انیمیشن باز شدن کارت‌ها، ظاهر شدن پنجره‌های مودال و انتقال بین view controllerها استفاده می‌شود. برخلاف انیمیشن 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
}

// انیمیشن تا ۷۵٪
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 با تابع زمانی خطی انیمیشن دهید.

آیا می‌توان از 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 برخلاف CALayer با masksToBounds نیازی به بافر offscreen برای ماسک کردن ندارد.
  • به عنوان ماسک برای CAGradientLayer استفاده می‌شود و اشکال با پرکننده گرادیانی ایجاد می‌کند.
  • برای خطوط نقطه‌چین از lineDashPattern با انیمیشن lineDashPhase برای اثر حرکت استفاده کنید.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید