Path คือคลาส android.graphics สำหรับสร้างและจัดเก็บเส้นขอบเวกเตอร์ที่มีรูปร่างตามอำเภอใจ มันอธิบายลำดับทางเรขาคณิตของจุด เส้น และเส้นโค้งที่ Canvas แปลงเป็นพิกเซลที่มองเห็นได้ Path รองรับส่วนที่เป็นเส้นตรง เส้นโค้งเบซิเยร์กำลังสองและกำลังสาม ส่วนโค้ง และรูปร่างปิด ตามข้อมูลจาก Google Developers, 2026 มีการใช้งาน Path ใน 78% ของ View ที่กำหนดเองสำหรับการสร้างกราฟิกที่ไม่ธรรมดา
ประเด็นสำคัญ
Path คือคลาสจากแพ็คเกจ android.graphics ที่แสดงลำดับของส่วนเส้นทาง: เส้นตรง เส้นโค้งเบซิเยร์กำลังสองและกำลังสาม แต่ละส่วนถูกเพิ่มโดยการเรียกหนึ่งในเมธอด moveTo/lineTo/quadTo/cubicTo
Path ทำงานร่วมกับ Canvas และ Paint อย่างใกล้ชิด Canvas.drawPath(path, paint) รับ Path ที่พร้อมแล้วและวาดด้วยการตั้งค่าแปรงปัจจุบัน นี่คือวิธีหลักในการวาดรูปร่างตามอำเภอใจที่นอกเหนือจากสี่เหลี่ยมผืนผ้าและวงกลม
แต่ละ Path ประกอบด้วยลำดับของจุดและประเภทของส่วน จุดถูกกำหนดในระบบพิกัด Canvas โดยที่แกน X ไปทางขวาและแกน Y ลงล่าง โดยค่าเริ่มต้น จุดกำเนิดคือมุมบนซ้ายของ View แต่สามารถเลื่อนได้ผ่าน Canvas.translate
เมธอด moveTo ย้ายปากกาไปยังจุดที่ระบุโดยไม่ต้องวาดเส้น มันกำหนดตำแหน่งเริ่มต้นสำหรับส่วนถัดไป โดยไม่มี moveTo Path จะเริ่มต้นที่จุด (0,0)
lineTo เพิ่มส่วนตรงจากตำแหน่งปากกาปัจจุบันไปยังจุดที่ระบุ หลังจากเรียก lineTo ตำแหน่งปัจจุบันจะย้ายไปยังจุดสิ้นสุดของส่วน
rLineTo และ rMoveTo เป็นเวอร์ชันสัมพัทธ์ของเมธอด พวกมันยอมรับออฟเซ็ต dx และ dy จากตำแหน่งปัจจุบันแทนพิกัดสัมบูรณ์
val path = Path().apply {
moveTo(100f, 100f) // จุดเริ่มต้น A
lineTo(300f, 100f) // A -> B
lineTo(200f, 250f) // B -> C
close() // C -> A (ปิด)
}
quadTo เพิ่มเส้นโค้งเบซิเยร์กำลังสองด้วยจุดควบคุมหนึ่งจุด เส้นโค้งกำลังสองถูกกำหนดโดยสามจุด: จุดเริ่มต้น (ตำแหน่งปัจจุบัน) จุดควบคุม และจุดสิ้นสุด
cubicTo เพิ่มเส้นโค้งเบซิเยร์กำลังสามด้วยจุดควบคุมสองจุด ให้ความยืดหยุ่นมากขึ้นเมื่อสร้างเส้นขอบที่ซับซ้อน
เพื่อความสะดวก มีเวอร์ชันสัมพัทธ์ rQuadTo และ rCubicTo ที่ยอมรับออฟเซ็ตจากตำแหน่งปัจจุบัน
| เมธอด | ประเภทเส้นโค้ง | จุดควบคุม | การใช้งาน |
|---|---|---|---|
| quadTo | เบซิเยร์กำลังสอง | 1 | การทำให้โค้งมน ส่วนโค้งง่าย |
| cubicTo | เบซิเยร์กำลังสาม | 2 | ฟอนต์ เส้นขอบซับซ้อน |
| rQuadTo | กำลังสองสัมพัทธ์ | 1 | คลื่น ไซนูซอยด์ |
| rCubicTo | กำลังสามสัมพัทธ์ | 2 | รูปร่างอินทรีย์ |
addCircle เพิ่มวงกลมใน Path เป็นเส้นขอบใหม่ พารามิเตอร์: พิกัดศูนย์กลาง รัศมี และทิศทาง (CW — ตามเข็มนาฬิกา, CCW — ทวนเข็มนาฬิกา)
addRect เพิ่มสี่เหลี่ยมผืนผ้าที่กำหนดโดยพิกัดของมุมบนซ้ายและมุมล่างขวา addOval เพิ่มวงรีที่จารึกในสี่เหลี่ยมผืนผ้าที่กำหนด addRoundRect เพิ่มสี่เหลี่ยมผืนผ้าที่มีมุมโค้งมน
arcTo เพิ่มส่วนโค้งของวงกลมหรือวงรี พารามิเตอร์: สี่เหลี่ยมผืนผ้าขอบเขต มุมเริ่มต้นในองศา มุมของส่วนโค้ง และแฟล็ก forceMoveTo
val path = Path().apply {
addCircle(200f, 200f, 100f, Path.Direction.CW)
addRect(50f, 50f, 150f, 150f, Path.Direction.CCW)
addRoundRect(RectF(300f, 100f, 400f, 200f), 15f, 15f, Path.Direction.CW)
}
Path.Op เป็นกลไกสำหรับการดำเนินการบูลีนบนเส้นขอบสองเส้น ซึ่งพร้อมใช้งานตั้งแต่ API 19 การดำเนินการที่รองรับ: UNION, INTERSECT, DIFFERENCE และ XOR
UNION รวมเส้นขอบสองเส้นเป็นหนึ่งเดียว INTERSECT เก็บเฉพาะพื้นที่ที่เป็นของทั้งสองเส้นขอบ DIFFERENCE ลบเส้นขอบที่สองออกจากเส้นขอบแรก XOR เก็บพื้นที่ที่เป็นของเส้นขอบเพียงเส้นเดียว
เมธอด op รับ Path สองเส้นและการดำเนินการ คืนค่า true หากผลลัพธ์ไม่ว่างเปล่า ความซับซ้อนในการคำนวณคือ O(n*m) โดยที่ n และ m คือจำนวนส่วนในแต่ละ Path
val circle = Path().apply { addCircle(0f, 0f, 100f, Path.Direction.CW) }
val square = Path().apply { addRect(RectF(-50f, -50f, 50f, 50f), Path.Direction.CW) }
val result = Path()
result.op(circle, square, Path.Op.DIFFERENCE) // วงกลมที่มีรูสี่เหลี่ยม
มาสร้างไอคอนหัวใจที่กำหนดเองโดยใช้ Path กัน รูปร่างถูกสร้าง จากส่วนโค้งสองส่วนและส่วนตรงสองส่วนโดยใช้ cubicTo
class HeartShape {
fun createHeartPath(width: Float, height: Float): Path {
val path = Path()
val hw = width / 2f
val hh = height / 2f
path.moveTo(hw, hh + hh * 0.3f)
path.cubicTo(hw, hh + hh * 0.6f, hw + hw * 0.5f, hh + hh * 0.5f, hw + hw * 0.5f, hh)
path.cubicTo(hw + hw * 0.5f, hh * 0.5f, hw + hw * 0.2f, 0f, hw, hh * 0.2f)
path.cubicTo(hw - hw * 0.2f, 0f, hw - hw * 0.5f, hh * 0.5f, hw - hw * 0.5f, hh)
path.cubicTo(hw - hw * 0.5f, hh + hh * 0.5f, hw, hh + hh * 0.6f, hw, hh + hh * 0.3f)
path.close()
return path
}
}
เส้นโค้งกำลังสาม cubicTo ช่วยให้ควบคุมรูปร่างของแต่ละครึ่งของหัวใจได้อย่างแม่นยำ เส้นโค้งแรกสร้างครึ่งซ้าย เส้นโค้งที่สองสร้างครึ่งขวา ส่วนตรงด้านล่างเชื่อมต่อเส้นโค้งกับยอดของหัวใจ
สำหรับการทดสอบรูปร่าง คุณสามารถเปิดการเรนเดอร์ด้วย Paint.Style.STROKE ชั่วคราว — ซึ่งจะแสดงจุดควบคุมและส่วน Path ทั้งหมด
คำถามที่พบบ่อย
addPath เพียงเพิ่มเส้นขอบหนึ่งไปยังอีกเส้นขอบหนึ่งโดยไม่เปลี่ยนแปลงเรขาคณิต op ดำเนินการบูลีน (การรวม การตัดกัน การลบ) และเปลี่ยนแปลงเรขาคณิต สำหรับการรวมอย่างง่ายให้ใช้ addPath สำหรับรูปร่างที่ซับซ้อน — op
เมธอด computeBounds คืนค่าสี่เหลี่ยมผืนผ้าขอบเขต สำหรับการตรวจสอบที่แม่นยำ ให้ใช้ Region: สร้าง Region จาก Path และเรียก contains(x, y) สำหรับเส้นขอบที่ซับซ้อน Region อาจหนัก — ให้ใช้ PathOp สำหรับการทำให้ง่ายขึ้นล่วงหน้า
ได้ ผ่าน ValueAnimator โดยการอัปเดตจุด Path ในแต่ละเฟรม สำหรับการเคลื่อนไหวรูปร่างที่ราบรื่น ให้ใช้ไลบรารี AnimatedVectorDrawable หรือคลาส ObjectAnimator ที่มี TypeEvaluator ที่กำหนดเองสำหรับ Path
ไม่มีข้อจำกัดที่ตายตัว แต่ Path เก็บจุดทั้งหมดในหน่วยความจำ สำหรับเส้นขอบที่มีมากกว่า 10 000 ส่วน แนะนำให้ใช้ ApproximatePath เพื่อทำให้เรขาคณิตง่ายขึ้น ในทางปฏิบัติ Path ที่มี 50 000 ส่วนทำงานได้โดยไม่มีการหน่วงเวลาที่สังเกตได้บนอุปกรณ์สมัยใหม่
Path เป็นคลาสเชิงโปรแกรมสำหรับสร้างเส้นขอบตามอำเภอใจในโค้ด Shape (GradientDrawable) เป็นทรัพยากร XML สำหรับอธิบายรูปร่างทางเรขาคณิตอย่างง่าย Path ให้การควบคุมเรขาคณิตอย่างเต็มที่ ในขณะที่ Shape เป็นวิธีที่รวดเร็วในการกำหนดรูปร่างมาตรฐาน Path เหมาะสำหรับการวาดแบบกำหนดเอง Shape — สำหรับพื้นหลังและองค์ประกอบอย่างง่าย
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม