มารู้จักกับ HTML5 Canvas กันดีกว่า

สวัสดีครับ มาเรียนรู้พื้นฐานของ HTML5 Canvas กันดีกว่า โดยเนื้อหานี้จะอธิบายถึง Canvas วิธีใช้งาน และตัวอย่างการใช้งาน เพื่อต่อยอดไปเขียนเกม ในบทถัดไปครับ
HTML5 Canvas คืออะไร?
Canvas คือ HTML element ที่ เปรียบเสมือนกับกระดานวาดภาพ ที่เราสามารถวาดภาพ โดยใช้ JavaScript เพื่อเขียนโค้ดเพื่อวาดภาพ หรือสร้าง animation ได้
เราสามารถสร้าง canvas ได้ด้วยการใช้ HTML <canvas>
กำหนดขนาดของ canvas โดยใช้ attribute width
และ height
(ขนาด default คือกว้าง 300x150 px) ดังนี้
<canvas id="myCanvas" width="500" height="500"> เบราว์เซอร์ของคุณไม่รองรับ Canvas กรุณาอัปเดตเบราว์เซอร์</canvas>
การใช้งาน canvas และ context
const canvas = document.getElementById('myCanvas')const ctx = canvas.getContext('2d')
ตัวอย่างการวาดสี่เหลี่ยมสีแดงลงบน canvas
ctx.fillStyle = 'red'ctx.fillRect(10, 10, 100, 100)
ระบบพิกัดของ Canvas
Canvas มีระบบพิกัดที่เริ่มต้นจากจุด (0, 0) ซึ่งอยู่ที่มุมซ้ายบนของ canvas ระบบพิกัดนี้มีแกน x และแกน y ที่แบ่ง canvas เป็น 4 ด้าน
- จุดเริ่มต้น :
(0, 0)
มุมซ้ายบน - แกน x : เพิ่มขึ้นไปทางขวา
- แกน y : เพิ่มขึ้นไปทางล่าง
Drawing
ด้านบนเราเห็นตัวอย่างการวาดสีเหลี่ยมกันไปแล้ว เรามาทำความเข้าใจเพิ่มกันดีกว่า
วาดสี่เหลี่ยม rectangles
จะมีด้วยกัน 3 แบบคือ
fillRect(x, y, width, height)
- วาดสี่เหลี่ยมที่มีสีพื้นหลังstrokeRect(x, y, width, height)
- วาดสี่เหลี่ยมที่มีเส้นขอบclearRect(x, y, width, height)
- ล้างสี่เหลี่ยม
เป็นการวาดสี่เหลี่ยมที่มีสีพื้นหลัง ลงไปใน canvas โดยใช้ค่า x, y ในการระบุตำแหน่งมุมซ้ายบนของสี่เหลี่ยม และค่า width, height ในการระบุขนาดของสี่เหลี่ยม ตัวอย่างด้านล่างคือ
- วาดสี่เหลี่ยมที่ตำแหน่ง x = 10, y = 10
- มีขนาด width = 100, height = 100
ctx.fillStyle = 'red'ctx.fillRect(10, 10, 100, 100)
ต่อมา strokeRect(x, y, width, height)
- วาดสี่เหลี่ยมที่มีเส้นขอบ (อันนี้วาดเส้น ไม่ได้ระบายถมทับทั่งสี่เลี่ยมนะครับ)
ctx.strokeStyle = 'blue'ctx.strokeRect(10, 10, 100, 100)
สุดท้าย clearRect(x, y, width, height)
- ล้างสี่เหลี่ยม เอาไว้ลบ สี่เหลี่ยม เหมือนคล้ายๆ ยางลบใน Paint ส่วนใหญ่ เอาไว้ clear canvas
ctx.clearRect(10, 10, 100, 100)
วาดเส้น paths
paths คือการวาดเส้นที่มีเส้นขอบ แต่ไม่มีพื้นหลัง เริ่มต้นด้วย beginPath
ตามด้วย moveTo(x, y)
และ lineTo(x, y)
ตามด้วย stroke()
เพื่อวาดเส้น เช่น
ctx.beginPath()ctx.moveTo(10, 10)ctx.lineTo(100, 100)ctx.stroke() // หรือ ctx.fill()
วาดวงกลม
ใช้ arc(x, y, radius, startAngle, endAngle)
เพื่อวาดวงกลม
Math.PI
คือ 180 องศาMath.PI * 2
คือ 360 องศา
ctx.beginPath()ctx.arc(50, 50, 30, 0, Math.PI * 2)ctx.stroke()
วาดเส้น Line
ใช้ lineTo(x, y)
เพื่อวาดเส้นตรง เริ่มต้นต้น beginPath()
และจบด้วย stroke()
หรือ fill()
ตามที่ต้องการ
ctx.beginPath()ctx.moveTo(10, 10)ctx.lineTo(100, 100)ctx.stroke()
ตัวอย่าง Canvas ทั้งหมด
ctx = canvas.getContext('2d')// 1. สี่เหลี่ยม (เต็ม)ctx.fillStyle = '#f00'ctx.fillRect(50, 50, 100, 80)
// 2. สี่เหลี่ยม (ขอบเท่านั้น)ctx.strokeStyle = '#0f0'ctx.lineWidth = 3ctx.strokeRect(200, 50, 100, 80)
// 3. วงกลมctx.fillStyle = '#2ecc71'ctx.beginPath()ctx.arc(400, 90, 40, 0, Math.PI * 2)ctx.fill()
// 4. เส้นctx.strokeStyle = '34df50'ctx.lineWidth = 5ctx.beginPath()ctx.moveTo(50, 200)ctx.lineTo(200, 250)ctx.stroke()
// 5. ตัวหนังสือctx.fillStyle = '#00f'ctx.font = '24px Arial'ctx.textAlign = 'left'ctx.fillText('Ahoy!', 250, 230)
ตัวอย่างข้อผิดพลาดที่มักพบบ่อยๆ
ลืมล้าง Canvas
// ❌ ผิด - รูปทรงจะซ้อนทับกันfunction draw() { ctx.fillRect(x, y, 50, 50)}
// ✅ ถูก - ล้างก่อนวาดใหม่function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillRect(x, y, 50, 50)}
ลืมปิด Path
// ❌ ผิด - อาจได้ผลการวาดที่ไม่คาดคิดctx.beginPath()ctx.arc(100, 100, 50, 0, Math.PI * 2)ctx.fill()ctx.arc(200, 100, 50, 0, Math.PI * 2) // ยังคงอยู่ใน path เดิม!ctx.fill()
// ✅ ถูก - แต่ละรูปทรงมี path ของตัวเองctx.beginPath()ctx.arc(100, 100, 50, 0, Math.PI * 2)ctx.fill()
ctx.beginPath()ctx.arc(200, 100, 50, 0, Math.PI * 2)ctx.fill()
Basic animations
การที่จะบังคับ animation เราสามารถทำได้หลักๆ คือ ใช้
setInterval()
setTimeout()
requestAnimationFrame()
ตัวอย่างการใช้ setInterval()
เพื่อให้รูปทรงขยับไปทางขวา
let x = 0
// ทุกๆ 100 มิลลิวินาที เลื่อนไปทางขวา 5 หน่วย (pixel)setInterval(() => { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillRect(x, 100, 50, 50) x += 5}, 100)
ตัวอย่าง setTimeout()
เพื่อให้รูปทรงขยับไปทางขวา
let x = 0
// ทุกๆ 100 มิลลิวินาที เลื่อนไปทางขวา 5 หน่วย (pixel)setTimeout(() => { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillRect(x, 100, 50, 50) x += 5}, 100)
ตัวอย่าง requestAnimationFrame()
เพื่อให้รูปทรงขยับไปทางขวา
let x = 0
// ทุกเฟรม เลื่อนไปทางขวา 5 หน่วย (pixel)requestAnimationFrame(() => { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillRect(x, 100, 50, 50) x += 5})
ปกติ เราจะสร้าง function เพื่อเอาไว้ reuse ในการเคลื่อนที่รูปทรง
function moveRight() { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.fillRect(x, 100, 50, 50) x += 5
if (x > canvas.width) { x = 0 } requestAnimationFrame(moveRight)}
moveRight()
สรุป
ตัวอย่างบทความนี้เป็นตัวอย่างการใช้ Canvas ในการวาดภาพ และใช้ requestAnimationFrame()
เพื่อทำ animation ให้รูปภาพขยับไปในทิศทาง ต่างๆ ที่เราต้องการ โดยใช้ แนวแกน x, y
หวังว่าบทความนี้จะช่วยให้คุณเข้าใจการใช้ Canvas ในการวาดภาพ และทำ animation ได้ดีขึ้น แล้วเดี๋ยวบทความต่อไป ลองมาทำเกมง่ายๆ ด้วย HTML5 Canvas กันครับ
Happy Coding ❤️
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust