CAShapeLayer — คืออะไร คุณสมบัติและการสร้างรูปทรง

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-12 เวลาอ่าน: 10 นาที

CAShapeLayer เป็นคลาสย่อยของ CALayer ที่ออกแบบมาสำหรับการเรนเดอร์เส้นทางเวกเตอร์แบบเร่งด้วยฮาร์ดแวร์บน GPU แตกต่างจาก CALayer พื้นฐานที่ทำงานกับภาพแรสเตอร์ผ่าน contents โดย CAShapeLayer จะเรนเดอร์รูปทรงตามอำเภอใจที่กำหนดผ่าน CGPath โดยไม่ต้องสร้างบัฟเฟอร์นอกหน้าจอแยกต่างหาก ตาม Apple QuartzCore Documentation, 2025 CAShapeLayer ใช้การเร่งด้วยฮาร์ดแวร์สำหรับการปรับขอบให้เรียบและรองรับแอนิเมชัน path, strokeStart และ strokeEnd เป็นเครื่องมือมาตรฐานสำหรับสร้างไอคอน ตัวบ่งชี้ความคืบหน้า และมาสก์ใน iOS

ประเด็นสำคัญ

  • CAShapeLayer — คลาสย่อยของ CALayer สำหรับเรนเดอร์รูปทรงเวกเตอร์บน GPU ผ่าน CGPath
  • การเรนเดอร์ เส้นทาง ดำเนินการโดยฮาร์ดแวร์โดยไม่สร้างบัฟเฟอร์แรสเตอร์กลาง — เร็วกว่า Core Graphics
  • คุณสมบัติ fillColor, strokeColor, lineWidth, lineCap, lineJoin ควบคุมลักษณะของรูปทรง
  • แอนิเมชันเส้นทาง ช่วยให้เปลี่ยนรูปทรงหนึ่งไปสู่อีกรูปทรงหนึ่งอย่างราบรื่น — ความสามารถหลักสำหรับแอนิเมชัน 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 ส่งคำสั่งโดยตรงไปยัง GPU ผ่าน Metal ผลลัพธ์คือประสิทธิภาพที่สูงขึ้น โดยเฉพาะระหว่างแอนิเมชัน

CAShapeLayer มีประโยชน์อย่างยิ่งสำหรับองค์ประกอบอินเทอร์เฟซที่เปลี่ยนรูปร่างเพื่อตอบสนองต่อการกระทำของผู้ใช้: ตัวบ่งชี้ความคืบหน้า, แผนภูมิ, ไอคอนแถบแท็บ, มาสก์สำหรับแอนิเมชันการเปิดเผยเนื้อหา

CAShapeLayer เรนเดอร์เส้นทางบน GPU อย่างไร

กระบวนการเรนเดอร์ของ CAShapeLayer แตกต่างจาก CALayer พื้นฐาน แทนที่จะเก็บบัฟเฟอร์แรสเตอร์ที่มีพิกเซล CAShapeLayer ส่งคำอธิบายจุดยอดของเส้นทางไปยัง GPU — ชุดของจุด, เส้นโค้งเบซิเยร์ และส่วนของเส้นตรง GPU จะแรสเตอร์เส้นทางนี้ในรอบเดียว โดยใช้สีเติมและสีเส้นขอบในขั้นตอน fragment shader

วิธีการนี้มีข้อดีสองประการ: การปรับขนาดโดยไม่สูญเสียคุณภาพ (กราฟิกเวกเตอร์ยังคงคมชัดที่ความละเอียดใดๆ) และแอนิเมชันที่มีประสิทธิภาพ — เมื่อเส้นทางเปลี่ยนไป GPU จะคำนวณเฉพาะพิกเซลที่เปลี่ยนแปลงเท่านั้น ไม่ใช่ทั้งหน้าจอ

คุณสมบัติหลักของ CAShapeLayer

path — คุณสมบัติหลักของ CAShapeLayer ที่รับ CGPath เส้นทางสามารถประกอบด้วยเส้นตรง, ส่วนโค้ง, เส้นโค้งเบซิเยร์ และสี่เหลี่ยมผืนผ้า สร้างผ่าน 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 — ความยาว miter สูงสุดเมื่อ lineJoin = .miter ป้องกันมุมที่ยาวไม่จำกัด

คุณสมบัติ lineDashPattern ช่วยให้สร้างเส้นประได้ รับอาร์เรย์ของตัวเลข: [6, 3] หมายถึง 6 จุดของขีดและ 3 จุดของช่องว่าง lineDashPhase กำหนดออฟเซ็ตรูปแบบและสามารถทำให้เคลื่อนไหวเพื่อเอฟเฟกต์ขีดเคลื่อนที่

CAShapeLayer กับ CALayer: เมื่อใดควรเลือกแบบไหน

การเลือกระหว่าง CAShapeLayer และ CALayer พื้นฐานขึ้นอยู่กับประเภทของเนื้อหา ถ้าองค์ประกอบเป็นพื้นที่สี่เหลี่ยมที่มีพื้นหลัง เส้นขอบ และเงา — CALayer ก็เพียงพอ ถ้าองค์ประกอบมีรูปร่างตามอำเภอใจ ต้องการแอนิเมชันเส้นทางหรือการปรับขนาดโดยไม่สูญเสียคุณภาพ — CAShapeLayer เหมาะกว่า

ประสิทธิภาพก็แตกต่างกันด้วย CALayer ที่มี cornerRadius และ masksToBounds จะสร้างบัฟเฟอร์นอกหน้าจอสำหรับการตัดเนื้อหา เพิ่ม 2–5 มิลลิวินาทีต่อเฟรม CAShapeLayer ไม่ต้องการบัฟเฟอร์นอกหน้าจอ — การตัดทำที่ระดับ vertex shader สำหรับองค์ประกอบที่มีมาสก์ซับซ้อน CAShapeLayer อาจเร็วกว่า 2–3 เท่า

  • CALayer: องค์ประกอบสี่เหลี่ยม, รูปภาพ, วิดีโอ, เนื้อหามุมมน (cornerRadius), เงา, เส้นขอบ
  • CAShapeLayer: ไอคอน, แผนภูมิ, แถบความคืบหน้า, มาสก์รูปร่างตามอำเภอใจ, เส้นทางเคลื่อนไหว, รูปทรงสำหรับแอนิเมชันเปิดเผย
  • CATextLayer: ข้อความที่ต้องการการเรนเดอร์ระดับย่อยพิกเซลและการแคชกลิฟ
  • CAGradientLayer: การเติมสีไล่ระดับ — รวมกับ CAShapeLayer ผ่าน mask เพื่อสร้างรูปทรงที่มีการไล่ระดับสี

การรวม CAShapeLayer กับเลเยอร์อื่นเป็นรูปแบบที่พบบ่อย ตัวอย่างเช่น CAGradientLayer ใช้ CAShapeLayer เป็นมาสก์เพื่อสร้างรูปทรงที่มีการเติมสีไล่ระดับ วิธีการนี้ให้ทั้งคุณภาพเวกเตอร์และการเติมสีไล่ระดับโดยไม่สูญเสียประสิทธิภาพ

แอนิเมชัน CAShapeLayer: path และ stroke

แอนิเมชันเส้นทาง เป็นหนึ่งในความสามารถที่ทรงพลังที่สุดของ CAShapeLayer ถ้าทั้งสองเส้นทาง (เริ่มต้นและสิ้นสุด) มีจำนวนจุดควบคุมและส่วนเท่ากัน Core Animation จะทำการประมาณค่าระหว่างกลางอย่างราบรื่น ผลลัพธ์คือเอฟเฟกต์การเปลี่ยนรูปทรงหนึ่งไปสู่อีกรูปทรงหนึ่ง

เงื่อนไขความเข้ากันได้ของเส้นทาง: UIBezierPath เริ่มต้นและสิ้นสุดต้องมีโครงสร้างเดียวกัน — จำนวนการเรียก moveTo, addLine, addCurve และ addQuadCurve ต้องตรงกัน ถ้าโครงสร้างต่างกัน แอนิเมชันจะเกิดขึ้นทันทีโดยไม่มีการประมาณค่าระหว่างกลาง

ตาม Apple WWDC 2024 การรวมกันของ strokeStart และ strokeEnd เป็นรูปแบบแอนิเมชัน CAShapeLayer ที่ใช้บ่อยที่สุด การทำให้ strokeEnd เคลื่อนไหวจาก 0.0 ถึง 1.0 สร้างเอฟเฟกต์การวาดเส้นทางจากต้นจนจบ ใช้ในตัวบ่งชี้การโหลด, แอนิเมชันเปิดเผยแผนภูมิ และการเปลี่ยนหน้าจอแบบกำหนดเอง

เพื่อสร้างเอฟเฟกต์เต้นเป็นจังหวะ ให้ทำให้ strokeEnd และ opacity เคลื่อนไหวพร้อมกันด้วยฟังก์ชันเวลาที่ต่างกัน สำหรับเอฟเฟกต์มดเดิน ให้ทำให้ lineDashPhase เคลื่อนไหวด้วย lineDashPattern คงที่ ทั้งสองเทคนิค implement ผ่าน CABasicAnimation โดยไม่ต้องใช้ CPU

แอนิเมชันเป็นมาสก์

CAShapeLayer มักใช้เป็น มาสก์ สำหรับเลเยอร์อื่น ตัวอย่างเช่น สำหรับแอนิเมชันเปิดเผยเนื้อหา: ในระยะเริ่มต้น mask.path เป็นสี่เหลี่ยมผืนผ้าขนาดศูนย์ และสุดท้ายเป็นขนาดเต็ม Core Animation จะประมาณค่าเส้นทางและเนื้อหาจะเปิดเผยอย่างราบรื่น

รูปแบบนี้ใช้ใน iOS สำหรับแอนิเมชันขยายการ์ด, การแสดงหน้าต่างโมดอล และการเปลี่ยนระหว่าง view controllers แตกต่างจากแอนิเมชัน 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
}

// เคลื่อนไหวเป็น 75%
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 ไม่ต้องการการวาดใหม่เมื่อเปลี่ยนขนาด — รูปทรงปรับขนาดแบบเวกเตอร์

ทำไมแอนิเมชันเส้นทางจึงไม่ทำงานอย่างราบรื่น?

แอนิเมชันเส้นทางที่ราบรื่นต้องการ โครงสร้างที่เหมือนกัน ของ UIBezierPath เริ่มต้นและสิ้นสุด จำนวนการเรียก moveTo, addLine, addCurve ต้องตรงกัน ใช้ UIBezierPath ที่มีจำนวนส่วนเท่ากันสำหรับรูปทรงเริ่มต้นและสิ้นสุด

วิธีสร้างเส้นประใน CAShapeLayer?

ตั้งค่า lineDashPattern — อาร์เรย์ของตัวเลขที่สลับความยาวขีดและช่องว่าง ตัวอย่างเช่น [8, 4] สร้างขีด 8pt และช่องว่าง 4pt สำหรับเอฟเฟกต์มดเดิน ให้ทำให้ lineDashPhase เคลื่อนไหวผ่าน CABasicAnimation ด้วยฟังก์ชันเวลาเชิงเส้น

สามารถใช้ CAShapeLayer เป็นมาสก์ได้หรือไม่?

ได้ นี่เป็นหนึ่งในกรณีการใช้งานหลัก กำหนด CAShapeLayer ให้กับคุณสมบัติ mask ของ CALayer ใดๆ รวมถึง CAGradientLayer และคลาสย่อยอื่นๆ การทำให้เส้นทางมาสก์เคลื่อนไหวสร้างเอฟเฟกต์การเปิดเผยเนื้อหาอย่างราบรื่นผ่านรูปทรงตามอำเภอใจ

วิธีเติมสีไล่ระดับให้รูปทรงผ่าน CAShapeLayer?

สร้าง CAGradientLayer และตั้งค่า mask = CAShapeLayer ที่มีเส้นทางที่ต้องการ สีไล่ระดับจะมองเห็นได้เฉพาะภายในเส้นทางมาสก์ รูปแบบนี้รวมข้อดีของรูปทรงเวกเตอร์ของ CAShapeLayer และการเติมสีไล่ระดับของ CAGradientLayer

สรุป

  • CAShapeLayer — คลาสย่อยของ CALayer สำหรับการเรนเดอร์เส้นทางเวกเตอร์แบบเร่งด้วยฮาร์ดแวร์บน GPU ผ่าน CGPath
  • คุณสมบัติหลัก: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, strokeStart, strokeEnd
  • แอนิเมชัน path สร้างการเปลี่ยนรูปทรง — ต้องการโครงสร้างที่เหมือนกันของเส้นทางเริ่มต้นและสิ้นสุด
  • แอนิเมชัน strokeEnd — รูปแบบมาตรฐานสำหรับตัวบ่งชี้ความคืบหน้าและการวาดเส้นทาง
  • CAShapeLayer ไม่ต้องการบัฟเฟอร์นอกหน้าจอสำหรับการทำมาสก์ แตกต่างจาก CALayer ที่มี masksToBounds
  • ใช้เป็นมาสก์สำหรับ CAGradientLayer สร้างรูปทรงที่มีการเติมสีไล่ระดับ
  • สำหรับเส้นประ ให้ใช้ lineDashPattern กับแอนิเมชัน lineDashPhase เพื่อเอฟเฟกต์การเคลื่อนไหว

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม