CAShapeLayer هو فئة فرعية من CALayer مصممة لعرض المسارات المتجهة المعجلة بالأجهزة على GPU. على عكس CALayer الأساسي الذي يعمل مع الصور النقطية عبر contents، يقوم 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 التسريع بالأجهزة للعرض. على عكس الرسم عبر Core Graphics في drawRect: حيث تقوم وحدة المعالجة المركزية بعرض المسار في سياق نقطي، يرسل CAShapeLayer الأوامر مباشرة إلى GPU عبر Metal. والنتيجة هي أداء أعلى، خاصة أثناء الرسوم المتحركة.
CAShapeLayer مفيد بشكل خاص لعناصر الواجهة التي تغير شكلها استجابة لإجراءات المستخدم: مؤشرات التقدم، الرسوم البيانية، أيقونات شريط التبويب، الأقنعة لرسوم الكشف عن المحتوى.
تختلف عملية عرض CAShapeLayer عن CALayer الأساسي. بدلاً من تخزين مخزن مؤقت نقطي بالبكسل، يمرر CAShapeLayer وصفًا رأسيًا للمسار إلى GPU — مجموعة من النقاط ومنحنيات بيزير وقطع الخطوط. يقوم GPU بترسيم هذا المسار في تمريرة واحدة، مع تطبيق ألوان التعبئة والحد في مرحلة تظليل الأجزاء.
يقدم هذا النهج ميزتين: تغيير الحجم دون فقدان الجودة (تبقى الرسومات المتجهة حادة في أي دقة) والرسوم المتحركة الفعالة — عندما يتغير المسار، يعيد GPU حساب البكسلات المتغيرة فقط، وليس الشاشة بأكملها.
path — الخاصية المركزية لـ CAShapeLayer، والتي تقبل CGPath. يمكن أن يحتوي المسار على خطوط وأقواس ومنحنيات بيزير ومستطيلات. يتم إنشاؤه عبر UIBezierPath في Swift أو CGPath في Core Graphics. مثال: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath ينشئ مستطيلًا دائريًا.
تتيح الخاصية lineDashPattern إنشاء خطوط متقطعة. تقبل مصفوفة من الأرقام: [6, 3] تعني 6 نقاط شرطة و 3 نقاط فراغ. يحدد lineDashPhase إزاحة النمط ويمكن تحريكه لتأثير شرطة متحركة.
يعتمد الاختيار بين CAShapeLayer و CALayer الأساسي على نوع المحتوى. إذا كان العنصر منطقة مستطيلة بخلفية وحدود وظل — فإن CALayer كافٍ. إذا كان للعنصر شكل عشوائي، أو يتطلب رسومًا متحركة للمسار أو تغيير حجم دون فقدان الجودة — فإن CAShapeLayer أفضل.
يختلف الأداء أيضًا. ينشئ CALayer مع cornerRadius و masksToBounds مخزنًا مؤقتًا خارج الشاشة لقص المحتوى، مما يضيف 2–5 مللي ثانية لكل إطار. لا يتطلب CAShapeLayer مخزنًا مؤقتًا خارج الشاشة — يتم القص على مستوى تظليل الرؤوس. للعناصر ذات الأقنعة المعقدة، يمكن أن يكون CAShapeLayer أسرع بمقدار 2–3 مرات.
يعد دمج CAShapeLayer مع الطبقات الأخرى نمطًا شائعًا. على سبيل المثال، يستخدم CAGradientLayer CAShapeLayer كقناع لإنشاء شكل بتعبئة متدرجة. يوفر هذا النهج جودة متجهة وتعبئة متدرجة دون فقدان الأداء.
الرسوم المتحركة للمسار هي واحدة من أقوى ميزات CAShapeLayer. إذا كان كلا المسارين (الأولي والنهائي) لهما نفس عدد نقاط التحكم والمقاطع، يقوم Core Animation باستيفاء سلس بينهما. والنتيجة هي تأثير تحويل شكل إلى آخر.
شرط توافق المسار: يجب أن يكون لـ UIBezierPath الأولي والنهائي نفس البنية — يجب أن يتطابق عدد استدعاءات moveTo و addLine و addCurve و addQuadCurve. إذا اختلفت البنية، سيكون الرسوم المتحركة فوريًا دون استيفاء.
وفقًا لـ Apple WWDC 2024، فإن مزيج strokeStart و strokeEnd هو نمط الرسوم المتحركة الأكثر استخدامًا في CAShapeLayer. يؤدي تحريك strokeEnd من 0.0 إلى 1.0 إلى إنشاء تأثير رسم المسار من البداية إلى النهاية. يُستخدم هذا في مؤشرات التحميل ورسوم كشف الرسوم البيانية والانتقالات المخصصة بين الشاشات.
لإنشاء تأثير نابض، قم بتحريك strokeEnd و opacity في وقت واحد مع وظائف توقيت مختلفة. لتأثير النمل الزاحف، قم بتحريك lineDashPhase مع lineDashPattern ثابت. يتم تنفيذ كلتا التقنيتين عبر CABasicAnimation دون مشاركة وحدة المعالجة المركزية.
غالبًا ما يُستخدم CAShapeLayer كـ قناع للطبقات الأخرى. على سبيل المثال، لرسوم الكشف عن المحتوى: في البداية، mask.path هو مستطيل بحجم صفري، والنهائي بالحجم الكامل. يقوم Core Animation باستيفاء المسار، وينكشف المحتوى بسلاسة.
يُستخدم هذا النمط في iOS لرسوم توسيع البطاقات وعرض النوافذ المشروطة والانتقالات بين وحدات التحكم في العرض. على عكس رسوم alpha، توفر رسوم قناع CAShapeLayer تأثير كشف أكثر طبيعية بأشكال عشوائية.
المثال الأول — إنشاء مؤشر تقدم دائري مع رسوم strokeEnd. هذا عنصر واجهة قياسي يوضح القدرات الأساسية لـ 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
}
// تحريك إلى 75%
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 يستخدم وحدة المعالجة المركزية للعرض في سياق نقطي — وهذا بطيء للرسوم المتحركة. يعرض CAShapeLayer المسار على GPU مما يعطي 60 إطارًا في الثانية أثناء رسوم path و strokeEnd والتحويلات. بالإضافة إلى ذلك، لا يتطلب CAShapeLayer إعادة رسم عند تغيير الحجم — يتم تغيير حجم الشكل بشكل متجه.
تتطلب رسوم المسار السلسة بنية متطابقة لـ UIBezierPath الأولي والنهائي. يجب أن يتطابق عدد استدعاءات moveTo و addLine و addCurve. استخدم UIBezierPath بنفس عدد المقاطع للأشكال الأولية والنهائية.
قم بتعيين lineDashPattern — مصفوفة من الأرقام تتناوب طول الشرطة والفراغ. على سبيل المثال، [8, 4] ينشئ شرطات 8 نقطة بفراغات 4 نقطة. لتأثير النمل الزاحف، قم بتحريك lineDashPhase عبر CABasicAnimation مع وظيفة توقيت خطية.
نعم، هذه واحدة من حالات الاستخدام الرئيسية. قم بتعيين CAShapeLayer لخاصية mask لأي CALayer، بما في ذلك CAGradientLayer والفئات الفرعية الأخرى. يؤدي تحريك مسار القناع إلى إنشاء تأثير كشف سلس للمحتوى عبر شكل عشوائي.
أنشئ CAGradientLayer واضبط mask = CAShapeLayer بالمسار المطلوب. سيكون التدرج مرئيًا فقط داخل مسار القناع. يجمع هذا النمط بين مزايا الشكل المتجه لـ CAShapeLayer والتعبئة المتدرجة لـ CAGradientLayer.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.