Matrix — คือคลาสจาก Android SDK (android.graphics.Matrix) ที่แสดงถึงการแปลงแบบ affine ผ่านเมทริกซ์ 3×3 ใช้สำหรับการแปลงวัตถุกราฟิก — การเคลื่อนที่ การปรับขนาด การหมุน และการเอียง ตามเอกสาร Android Developers Documentation (2026) Matrix เป็นเครื่องมือหลักสำหรับการทำงานกับการแปลงใน Canvas, Bitmap และ Drawable โดยให้การควบคุมพิกัดที่แม่นยำในการวาดแบบกำหนดเอง
สาระสำคัญ
Matrix (android.graphics.Matrix) — คือคลาส Android SDK ที่แสดงถึงเมทริกซ์ทางคณิตศาสตร์ขนาด 3×3 ใช้สำหรับการแปลงพิกัดสองมิติ Matrix เป็นองค์ประกอบพื้นฐานสำหรับการแปลงกราฟิกทั้งหมดใน Android — ตั้งแต่การเลื่อนและปรับขนาด Canvas ไปจนถึงการบิดเบือน Perspective ที่ซับซ้อนของ Bitmap
แตกต่างจาก iOS ที่ใช้โครงสร้างแยก CGAffineTransform (affine) และ CATransform3D (3D) Android รวมการแปลงแบบ affine และ perspective ไว้ในคลาสเดียวคือ Matrix เมทริกซ์ 3×3 ช่วยให้สามารถแสดงทั้งการดำเนินการ affine มาตรฐาน (แถวสุดท้าย [0, 0, 1]) และการบิดเบือนแบบ perspective เมื่อแถวสุดท้ายมีค่าใด ๆ ซึ่งให้ความยืดหยุ่นมากกว่า แต่ต้องเข้าใจคณิตศาสตร์ของเมทริกซ์
Matrix ทำงานร่วมกับ Canvas API อย่างใกล้ชิด เมื่อนักพัฒนาเรียก canvas.translate(), canvas.scale() หรือ canvas.rotate() เมธอดเหล่านี้จะปรับเปลี่ยนเมทริกซ์ของบริบทกราฟิกภายใน สามารถรับเมทริกซ์ปัจจุบันของ Canvas ได้ผ่าน canvas.getMatrix() และนำเมทริกซ์ที่กำหนดเองไปใช้ด้วยตนเองผ่าน canvas.setMatrix() หรือ canvas.concat()
Matrix รองรับการแปลงแบบ affine พื้นฐานสี่ประเภท: translate, scale, rotate, skew (เอียง) แต่ละประเภทมีเมธอดสำหรับการคูณหน้า (pre) การคูณหลัง (post) และการตั้งค่า (set) ความแตกต่างระหว่าง preTranslate และ postTranslate อยู่ที่ลำดับการคูณเมทริกซ์ ซึ่งส่งผลต่อการแปลงสุดท้ายเมื่อรวมกัน
| การดำเนินการ | เมธอด | พารามิเตอร์ | คำอธิบาย |
|---|---|---|---|
| Translate | setTranslate / preTranslate / postTranslate | dx, dy | เลื่อนตามแกน X และ Y |
| Scale | setScale / preScale / postScale | sx, sy, px, py | ปรับขนาดโดยมีจุดอ้างอิง |
| Rotate | setRotate / preRotate / postRotate | degrees, px, py | หมุนรอบจุดอ้างอิง |
| Skew | setSkew / preSkew / postSkew | kx, ky | เอียง (เฉือน) ตามแนวแกน |
Translate เปลี่ยนตำแหน่งของทุกจุดตามค่าการเลื่อน dx, dy ค่า dx ที่เป็นบวกจะเลื่อนไปทางขวา dy — ลง (ในระบบพิกัดหน้าจอ Android แกน Y จะชี้ลง) translate ไม่เปลี่ยนรูปร่างของวัตถุ — เฉพาะตำแหน่งเท่านั้น เป็นการดำเนินการที่ง่ายที่สุดและใช้บ่อยที่สุดสำหรับการจัดตำแหน่งองค์ประกอบ
Scale เปลี่ยนขนาดของวัตถุด้วยค่าสัมประสิทธิ์ sx (ตาม X) และ sy (ตาม Y) พารามิเตอร์ px, py กำหนดจุดอ้างอิงของการปรับขนาด (pivot point) หากไม่ระบุ px, py การปรับขนาดจะทำสัมพันธ์กับจุดกำเนิด (0, 0) เมื่อ sx = sy วัตถุจะถูกปรับขนาดอย่างสม่ำเสมอ ค่าลบจะสร้างการสะท้อน
Rotate หมุนวัตถุตามมุมที่กำหนด (เป็นองศา) รอบจุดอ้างอิง (px, py) ค่ามุมที่เป็นบวกหมายถึงการหมุนตามเข็มนาฬิกา (แตกต่างจาก iOS/macOS ที่มุมบวกหมายถึงทวนเข็มนาฬิกา) หากไม่ได้ระบุ px, py การหมุนจะทำรอบจุดกำเนิด
Skew (เฉือน) ทำให้วัตถุผิดรูป โดยเอียงตามแกน X (kx) หรือแกน Y (ky) ค่า 1.0 จะเอียง 45 องศา Skew ใช้สำหรับสร้างเอฟเฟกต์การเอียง เลียนแบบลักษณะสามมิติ (pseudo-3D) และการบิดเบือนเปอร์สเปคทีฟ
Matrix จัดเก็บองค์ประกอบของเมทริกซ์ 3×3 ในอาเรย์ภายในขนาด 9 ค่าทศนิยม (float[9]) ลำดับการจัดเก็บเป็นแบบ column-major (ตามคอลัมน์) ซึ่งสอดคล้องกับการแสดงทางคณิตศาสตร์มาตรฐาน การเข้าถึงแต่ละองค์ประกอบทำผ่านค่าคงที่: Matrix.MSCALE_X, Matrix.MSKEW_Y, Matrix.MTRANS_X และอื่น ๆ
เมทริกซ์ ถูกจัดเรียงดังนี้: สองคอลัมน์แรก (MSCALE_X, MSKEW_X, MSKEW_Y, MSCALE_Y) รับผิดชอบการปรับขนาด การหมุน และการเอียง คอลัมน์ที่สาม (MTRANS_X, MTRANS_Y, MPERSP_2) — สำหรับการเลื่อนและเปอร์สเปคทีฟ สำหรับการแปลงแบบ affine MPERSP_0 และ MPERSP_1 มีค่าเท่ากับ 0 และ MPERSP_2 มีค่าเท่ากับ 1
การรับค่าเมทริกซ์ใช้ getValues(float[] values) ซึ่งเติมอาเรย์ขนาด 9 องค์ประกอบ สำหรับการตั้งค่าใช้ setValues(float[] values) ซึ่งช่วยให้จัดการเมทริกซ์ได้โดยตรงสำหรับการแปลงที่ซับซ้อนซึ่งเกินขอบเขตของเมธอดมาตรฐาน translate, scale, rotate และ skew
Matrix มีเมธอดหลายตัวสำหรับการจำแนกสถานะปัจจุบัน isIdentity() ตรวจสอบว่าเมทริกซ์เป็นเมทริกซ์เอกลักษณ์หรือไม่ isAffine() — ตรวจสอบว่ามีเฉพาะการแปลงแบบ affine หรือไม่ (MPERSP_0 = 0, MPERSP_1 = 0, MPERSP_2 = 1) การตรวจสอบเหล่านี้มีประโยชน์สำหรับการปรับให้เหมาะสม: หากเมทริกซ์เป็นเมทริกซ์เอกลักษณ์ สามารถข้ามการแปลงได้
Matrix รองรับการดำเนินการหลายประเภท: การตั้งค่า (set) การคูณหน้า (pre) การคูณหลัง (post) การต่อกัน (concat) การผกผัน (invert) และการแมป (map) แต่ละประเภทมีหน้าที่ของตัวเองในการสร้างการแปลงที่ซับซ้อน
preTranslate คูณเมทริกซ์ปัจจุบันทางซ้ายด้วยเมทริกซ์การเลื่อน: result = translate × current postTranslate คูณทางขวา: result = current × translate ความแตกต่างอยู่ที่ลำดับการนำไปใช้: การดำเนินการ pre จะถูกนำไปใช้ก่อนการแปลงปัจจุบัน การดำเนินการ post — หลัง การทำงานเดียวกันนี้ใช้กับ preScale, postScale, preRotate, postRotate และ preSkew, postSkew
invert(Matrix inverse) คำนวณเมทริกซ์ผกผัน หากเมทริกซ์ต้นฉบับเป็นเอกฐาน (ดีเทอร์มิแนนต์เป็นศูนย์) จะคืนค่า false concat(Matrix other) คูณเมทริกซ์ปัจจุบันด้วยเมทริกซ์ที่ส่งเข้า: set = set × other สำหรับลำดับย้อนกลับ ใช้ setConcat(other, this)
mapRect(RectF rect) แปลงสี่เหลี่ยมผืนผ้าและคืนค่าผลลัพธ์ใน RectF ใหม่ mapPoints(float[] dst, float[] src) แปลงอาเรย์ของจุด mapVectors(float[] dst, float[] src) แปลงเวกเตอร์ — โดยไม่รวมการเลื่อน (translate) mapRect มีประโยชน์สำหรับการคำนวณ bounding box หลังการแปลง
Matrix ถูกใช้อย่างแพร่หลายในสองสถานการณ์หลักของกราฟิก Android: การแปลง Canvas และการแปลง Bitmap ในทั้งสองกรณี Matrix จะกำหนดว่าผลลัพธ์กราฟิกจะถูกเปลี่ยนแปลงอย่างไร
Canvas มีเมธอด canvas.setMatrix(matrix) สำหรับการแทนที่เมทริกซ์ปัจจุบันทั้งหมด และ canvas.concat(matrix) สำหรับการคูณการแปลงปัจจุบันด้วยเมทริกซ์ที่ส่งเข้า หลังจากใช้ Matrix การวาดทั้งหมดที่ตามมา — การเรียก drawBitmap, drawRect, drawPath — จะดำเนินการในระบบพิกัดที่ถูกแปลงแล้ว Canvas ยังมีสแต็กสถานะที่บันทึกไว้ของตัวเองผ่าน save() และ restore()
Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height, Matrix matrix, boolean filter) สร้าง Bitmap ใหม่ด้วยการใช้การแปลงที่กำหนด นี่เป็นเครื่องมือที่มีประสิทธิภาพสำหรับการสร้างสำเนาของภาพที่ปรับขนาด หมุน หรือบิดเบือน โดยไม่สูญเสีย Bitmap ต้นฉบับ พารามิเตอร์ filter ควบคุมการปรับให้เรียบในการประมาณค่าพิกเซล
setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) — ความสามารถเฉพาะของ Matrix ที่ไม่มีใน CGAffineTransform โดยคำนวณเมทริกซ์ที่แปลงจุดที่กำหนดจากรูปหลายเหลี่ยมหนึ่งไปยังอีกรูปหนึ่ง เมื่อ pointCount = 4 จะสร้างการแปลงแบบเปอร์สเปคทีฟ (projective) อย่างสมบูรณ์ ทำให้สามารถวางซ้อน Bitmap ด้วยการบิดเบือนเปอร์สเปคทีฟ
มาดู ตัวอย่างเชิงปฏิบัติ ของการใช้ Matrix สำหรับการแปลงกราฟิกในแอปพลิเคชัน Android ด้วย Kotlin
ตัวอย่างสร้าง Matrix สำหรับการแปลงแบบรวม: เลื่อนไปที่ (100, 50) ปรับขนาด 1.5 เท่า และหมุน 45 องศา การใช้ postTranslate หลังจาก preRotate และ preScale จะเปลี่ยนลำดับของการดำเนินการ
val matrix = Matrix()
matrix.preScale(1.5f, 1.5f)
matrix.preRotate(45f)
matrix.postTranslate(100f, 50f)
// ประยุกต์ใช้กับจุด
val pts = floatArrayOf(0f, 0f, 100f, 100f)
matrix.mapPoints(pts)
// ประยุกต์ใช้กับสี่เหลี่ยม
val rect = RectF(0f, 0f, 200f, 100f)
matrix.mapRect(rect)
ตัวอย่างสาธิต การใช้ Matrix กับ Canvas ใน onDraw สำหรับการหมุนและปรับขนาดวงกลมรอบจุดศูนย์กลาง การบันทึกและเรียกคืนสถานะ Canvas ช่วยให้มั่นใจว่าการแปลงจะไม่ส่งผลกระทบต่อองค์ประกอบการวาดที่ตามมา
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val cx = width / 2f
val cy = height / 2f
val radius = 100f
canvas.save()
val matrix = Matrix()
matrix.postTranslate(cx, cy)
matrix.postRotate(30f)
matrix.postScale(1.2f, 1.2f)
canvas.concat(matrix)
val paint = Paint().apply {
color = Color.BLUE
style = Paint.Style.FILL
}
canvas.drawCircle(0f, 0f, radius, paint)
canvas.restore()
}
ตัวอย่างใช้ setPolyToPoly เพื่อสร้างการบิดเบือนเปอร์สเปคทีฟของ Bitmap จุดต้นทางสี่จุด (มุมของสี่เหลี่ยมผืนผ้าต้นฉบับ) ถูกแมปไปยังจุดเป้าหมายสี่จุดที่สร้างเป็นรูปสี่เหลี่ยมคางหมู ผลลัพธ์คือเอฟเฟกต์ของภาพที่เอียงในพื้นที่สามมิติ
fun applyPerspective(
bitmap: Bitmap,
skew: Float
): Bitmap {
val w = bitmap.width.toFloat()
val h = bitmap.height.toFloat()
val src = floatArrayOf(0f, 0f, w, 0f,
0f, h, w, h)
val dst = floatArrayOf(skew, 0f, w - skew, 0f,
0f, h, w, h)
val matrix = Matrix()
matrix.setPolyToPoly(src, 0, dst, 0, 4)
return Bitmap.createBitmap(
bitmap, 0, 0,
w.toInt(), h.toInt(),
matrix, true
)
}
คำถามที่พบบ่อย
Matrix ทำงานกับการแปลงสองมิติแบบ affine และ perspective ผ่านเมทริกซ์ 3×3 หนึ่งตัว Camera (android.graphics.Camera) — เป็นคลาสระดับสูงกว่าที่จำลองกล้องสามมิติ: มันสร้างการหมุน 3D แล้วฉายผลลัพธ์ลงใน 2D Matrix Camera ใช้ Matrix ภายใน
สร้าง Matrix ด้วย postRotate(90f) และส่งต่อไปยัง Bitmap.createBitmap(original, 0, 0, w, h, matrix, true) โปรดทราบว่าเมื่อหมุน 90 องศา ความกว้างและความสูงของผลลัพธ์จะสลับกัน สำหรับการหมุนในมุมที่กำหนดเอง อาจต้องครอบตัดเพื่อหลีกเลี่ยงพื้นที่ว่าง
ใช้ matrix.invert(resultMatrix) เมธอดจะคืนค่า true หากการผกผันสำเร็จ และเขียนเมทริกซ์ผกผันลงใน resultMatrix การผกผันอาจเป็นไปไม่ได้หากเมทริกซ์เป็นเอกฐาน (เช่น เมื่อปรับขนาดเป็นศูนย์) ควรตรวจสอบค่าที่คืนกลับเสมอ
pre คูณการแปลงใหม่ทางซ้าย: result = operation × current — การดำเนินการจะถูกนำไปใช้ก่อนการแปลงปัจจุบัน post คูณทางขวา: result = current × operation — การดำเนินการจะถูกนำไปใช้หลัง สำหรับลำดับ preRotate + postTranslate: หมุนก่อน แล้วค่อยเลื่อน
ได้ Matrix ใช้ใน Jetpack Compose ผ่านคลาส android.graphics.Matrix ในการทำงานร่วมกับ Canvas ของ Compose ใน Compose มี graphicsLayer สำหรับการแปลง (scale, rotationX, translationX และอื่น ๆ) แต่สำหรับการแปลง Bitmap ที่ซับซ้อน จะใช้ Matrix ในโค้ด drawWithContent หรือ drawBehind
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ