CAShapeLayer — زیرکلاسی از CALayer است که برای رندر سختافزاری مسیرهای برداری روی GPU طراحی شده است. برخلاف CALayer پایه که با تصاویر شطرنجی از طریق contents کار میکند، CAShapeLayer اشکال دلخواه تعیین شده توسط CGPath را بدون ایجاد بافر جداگانه offscreen رندر میکند. طبق 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 در زمان رندر از شتاب سختافزاری استفاده میکند. برخلاف ترسیم از طریق Core Graphics در drawRect:، جایی که CPU مسیر را در یک بافت شطرنجی رندر میکند، CAShapeLayer دستورات را مستقیماً از طریق Metal به GPU ارسال میکند. نتیجه — عملکرد بالاتر، به ویژه در هنگام انیمیشن.
CAShapeLayer به ویژه برای عناصر رابط کاربری که در پاسخ به اقدامات کاربر شکل خود را تغییر میدهند مفید است: نشانگرهای پیشرفت، نمودارها، آیکونهای نوار تب، ماسکهای انیمیشن ظاهر شدن محتوا.
فرآیند رندر CAShapeLayer با CALayer پایه متفاوت است. به جای ذخیره بافر شطرنجی با پیکسلها، CAShapeLayer توصیف رأس مسیر را به GPU ارسال میکند — مجموعهای از نقاط، منحنیهای Bezier و قطعات. GPU این مسیر را در یک pass رستر میکند و رنگ پر کردن و ضربه را در مرحله shader قطعه اعمال میکند.
این رویکرد دو مزیت دارد: مقیاسپذیری بدون افت کیفیت (گرافیک برداری در هر وضوحی واضح میماند) و انیمیشن کارآمد — هنگام تغییر path، GPU فقط پیکسلهای تغییر یافته را دوباره محاسبه میکند، نه کل صفحه را.
path — ویژگی مرکزی CAShapeLayer که CGPath را میپذیرد. مسیر میتواند شامل خطوط، کمانها، منحنیهای Bezier و مستطیلها باشد. از طریق UIBezierPath در Swift یا CGPath در Core Graphics ایجاد میشود. مثال: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath یک مستطیل گرد ایجاد میکند.
ویژگی lineDashPattern امکان ایجاد خطوط نقطهچین را فراهم میکند. آرایهای از اعداد میپذیرد: [6, 3] به معنای 6 نقطه خط و 3 نقطه فاصله است. lineDashPhase جابجایی الگو را تعیین میکند و میتواند برای اثر خط نقطهچین متحرک انیمیشن داده شود.
انتخاب بین CAShapeLayer و CALayer پایه به نوع محتوا بستگی دارد. اگر عنصر یک ناحیه مستطیلی با پسزمینه، مرز و سایه است — CALayer کافی است. اگر عنصر شکل دلخواه دارد، نیاز به انیمیشن مسیر یا مقیاسپذیری بدون افت کیفیت دارد — CAShapeLayer ارجح است.
عملکرد نیز متفاوت است. CALayer با cornerRadius و masksToBounds یک بافر offscreen برای برش محتوا ایجاد میکند که 2–5 میلیثانیه به هر فریم اضافه میکند. CAShapeLayer به بافر offscreen نیاز ندارد — برش در سطح shader رأس انجام میشود. برای عناصر با ماسک پیچیده، CAShapeLayer میتواند 2–3 برابر سریعتر باشد.
ترکیب CAShapeLayer با لایههای دیگر یک الگوی رایج است. به عنوان مثال، CAGradientLayer از CAShapeLayer به عنوان ماسک برای ایجاد شکل با پرکننده گرادیانی استفاده میکند. این رویکرد هم کیفیت برداری و هم پرکننده گرادیانی را بدون افت عملکرد فراهم میکند.
انیمیشن 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 اثر طبیعیتری از ظاهر شدن با شکل دلخواه ایجاد میکند.
اولین نمونه — ایجاد نشانگر پیشرفت دایرهای با انیمیشن strokeEnd. این یک عنصر استاندارد UI است که قابلیتهای اصلی CAShapeLayer را نشان میدهد:
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 ساختار سازگاری دارند:
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 برای انیمیشن ظاهر شدن محتوا. ماسک از مرکز به لبهها گسترش مییابد:
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 رندر میکند که 60 FPS را در انیمیشن path، strokeEnd و تبدیلها ارائه میدهد. علاوه بر این، CAShapeLayer هنگام تغییر اندازه نیاز به بازرندر ندارد — شکل به صورت برداری مقیاس میشود.
انیمیشن نرم path نیاز به ساختار یکسان UIBezierPath آغازین و پایانی دارد. تعداد فراخوانیهای moveTo، addLine، addCurve باید مطابقت داشته باشد. از UIBezierPath با تعداد بخشهای یکسان برای شکل آغازین و پایانی استفاده کنید.
lineDashPattern را تنظیم کنید — آرایهای از اعداد که به ترتیب طول خط و فاصله را مشخص میکنند. به عنوان مثال، [8, 4] خطوط 8pt با فاصلههای 4pt ایجاد میکند. برای خط نقطهچین متحرک، lineDashPhase را از طریق CABasicAnimation با تابع زمانی خطی انیمیشن دهید.
بله، این یکی از سناریوهای اصلی است. CAShapeLayer را به ویژگی mask هر CALayer، از جمله CAGradientLayer و سایر زیرکلاسها، اختصاص دهید. انیمیشن path ماسک اثر ظاهر شدن نرم محتوا را از طریق شکلی با فرم دلخواه ایجاد میکند.
CAGradientLayer ایجاد کنید و mask آن را برابر CAShapeLayer با path مورد نظر قرار دهید. گرادیان فقط در داخل مسیر ماسک قابل مشاهده خواهد بود. این الگو مزایای شکل برداری CAShapeLayer را با پرکننده گرادیانی CAGradientLayer ترکیب میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.