HTML5 Canvas คืออะไร? + วิธีใช้งานเบื้องต้น
![HTML5 Canvas คืออะไร? + วิธีใช้งานเบื้องต้น](/_vercel/image?url=%2Fimages%2F2015%2F02%2Fcanvas.png&w=828&q=80)
HTML5 Canvas เป็นหนึ่งใน feature ที่มีคุณสมบัติทางด้านกราฟฟิคที่มาพร้อมกับ HTML5 โดยส่วนตัวเพิ่งเริ่มสนใจ Canvas ก็ตอนที่ได้ลองหัดทำเกมส์บน Browser นี่แหละครับ เลยไปนั่งอ่านและลองทำความเข้าใจอยู่ซักพัก สุดท้ายก็เลยเขียนและเรียบเรียงตามความเข้าใจของตัวเองไว้
ตัวอย่างนี้เป็นการทดลองและลองเล่น HTML5 Canvas โดยจะนำเสนอและวิธีการใช้งานและวาดรูปทรงต่างๆเบื้องต้น ทั้ง วาดสี่เหลี่ยม วาดวงกลม วาดเส้น แบบง่ายๆ :)
Canvas คืออะไร ?
Canvas เป็น Element หนึ่งใน HTML5 เหมือนอย่าง <img>
หรือ <a>
โดยใน <img>
หรือ <a>
จะมี attributes เช่น src
และ href
แต่ใน <canvas>
จะมีเพียงแค่ 2 attributes คือ width
และ height
(ความกว้างและความสูงของ Canvas) เท่านั้น
Note:
<canvas>
นั้น required closed tag ด้วยไม่เหมือนอย่าง<img>
ฉะนั้นก็อย่าลืมปิดแท็กด้วย</canvas>
นะครับ :)
ตัวอย่างเช่น
<canvas id="tutorial" width="150" height="150"></canvas>
เป็นการประกาศสร้าง Element <canvas>
ขึ้นมาโดยมี id ชื่อ canvas
และมีความกว้างและความสูง 150 pixels
Note: โดยปกติแล้ว
canvas
จะมีความกว้าง 300px และสูง 150px ถึงแม้ว่าเราจะไม่ได้กำหนดขนาดให้มันก็ตาม
ใช้งาน Canvas เบื้องต้น
เริ่มแรกทำการสร้างไฟล์ HTML ขึ้นมา ผมทำการตั้งชื่อว่า index.html
และมี element <canvas>
ดังตัวอย่าง
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" /> <title>HTML5 Canvas Tutorials</title> </head> <body> <canvas id="canvas" width="500" height="500"></canvas>
<script src="main.js"></script> </body></html>
จากนั้นลิงค์สคริปไปยังไฟล์ JavaScript ของเรา โดยทำการตั้งชื่อว่า main.js
var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')
จากโค๊ดด้านบน เราทำการเลือก element ที่มีไอดีว่า canvas
ซึ่งก็คือตัว <canvas>
จากนั้นทำการ getContext('2d')
เพื่อทำการใช้ canvas context แบบ 2d (เป็นออปเจ็คที่เอาไว้วาดและสร้างกราฟฟิคต่างๆ)
ระบบ Coordinate System
โดยปกติแล้ว หากได้เรียนคณิตศาสตร์มา จะพบว่าเราจะใช้การกำหนดแกน x, y ด้วยระบบ Cartesian coordinate system ซึ่งกำหนดจุด x, y จากการลากเส้นแกนทั้งสองตัดกันเป็นมุมฉาก
ส่วนระบบของ Canvas coordinate system จะต่างออกไป จะนับจุดบนซ้ายเป็นจุด 0,0 ดังตัวอย่างเปรียบเทียบในภาพด้านล่างครับ
วาดสี่เหลี่ยม
การวาดสี่เหลี่ยม สามารถใช้ฟังค์ชัน fillRect(x, y, width, height)
โดย x คือแกน x, y คือแกน y และ width, height คือความกว้างและความสูง ตามลำดับ
โดยเมื่อเราเลือก Element canvas
และทำการ getContext()
แล้ว เราสามารถวาดสี่เหลี่ยมแบบง่ายๆ ด้วยโค๊ดแบบนี้
// กำหนดสีcontext.fillStyle = 'green'// วาดสี่เหลี่ยม Rectangle (x, y, width, height)// โดยแกน x,y จะนับจากมุมบนซ้ายเป็นจุด 0, 0context.fillRect(10, 10, 100, 100)
See the Pen WbyJEV by Chai Phonbopit (@Phonbopit) on CodePen.
นอกจาก fillRect()
แล้ว เรายังสามารถใช้
strokeRect(x, y, width, height)
: เพื่อวาดสี่เหลี่ยมให้มีเฉพาะเส้นขอบclearRect(x, y, width, height)
: วาดสี่เหลี่ยมให้เป็น transparent หรืออีกในหนึ่งก็คือการลบ content อื่นๆ (เหมือนเป็นยางลบ)
เช่น
var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')
context.fillStyle = 'green'context.fillRect(10, 10, 100, 100)
context.strokeStyle = 'red'context.strokeRect(110, 110, 200, 200)
context.clearRect(35, 35, 50, 50)
See the Pen jEKxGO by Chai Phonbopit (@Phonbopit) on CodePen.
Paths
ให้นึกถึงเวลาคุณจับดินสอวาดรูป Path หนึ่งก็เหมือนกับการจิ้มดินสอลงบนกระดาษ เวลาคุณวาดรูป คุณก็จะมีการยกดินสอขึ้น และเลื่อนไปยังอีกตำแหน่งเพื่อวาดภาพต่อๆมา (ลองนึกว่าให้คุณวาดรูปแมวโดยไม่ยกดินสอซิ เปรียบเสมือนใช้ Canvas แค่ Path เดียว)
ฉะนั้น Path จะมีด้วยกัน 2 เมธอดคือ (ให้นึกถึงการใช้ดินสอวาดรูปเหมือนเดิม)
moveTo(x, y)
: หมายถึงเลื่อนดินสอไปยังตำแหน่งที่ต้องการ (จุดเริ่มต้น)lineTo(x, y)
: หมายถึงว่าลากเส้นไปถึงตำแหน่งไหน (จุดสุดท้ายที่ยกมือ)
เช่น
context.moveTo(0, 100)context.lineTo(200, 100)
แต่ว่ายังไม่มีอะไรเกิดขึ้น เนื่องจากว่าดินสอเราไส้หมดครับ ต้องเดิมไส้ใหม่ พอดีใช้ดินสอกด :)
context.strokeStyle = 'black';context.stroke();
วาดวงกลม
การวาดวงกลมจะใช้ context.arc()
ดังนี้ context.arc(x, y, radius, startAngle, endAngle, anticlockwise)
โดย
- x,y คือ แกน x และ y
- radius: รัศมีของวงกลม
- startAngle, endAngle คือ เรเดียน
- anticlockwise : ทวนเข็มหรือตามเข็มนาฬิกา (true/false)
เช่นตัวอย่าง จะทำการวาดวงกลม 2 วง วงแรกขนาดรัศมี 40 ตรงตำแหน่ง 50, 50 โดยวาดเฉพาะเส้นรอบวง และวงที่สองขนาดเท่ากัน ที่ตำแหน่ง 120, 120 และวาดทั้งวงกลม จะได้ดังนี้
var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')
context.beginPath()context.strokeStyle = 'black'context.lineWidth = 5context.arc(50, 50, 40, 0, Math.PI * 2, false)context.stroke()context.closePath()
context.beginPath()context.fillStyle = '#dd0343'context.arc(120, 120, 40, 0, Math.PI * 2)context.fill()context.closePath()
See the Pen GgGdOw by Chai Phonbopit (@Phonbopit) on CodePen.
วาดเส้น
การวาดเส้นบน Canvas
เราจะใช้ร่วมกับการใช้ Path โดยมีฟังค์ชันที่สำคัญดังนี้
context.beginPath()
: สำหรับกำหนด pathcontext.moveTo(x, y)
: ตำแหน่งเริ่มต้นในการวาดcontext.lineTo(x, y)
: ตำแหน่งสิ้นสุดการวาดcontext.lineWidth
: เอาไว้กำหนดขนาดของเส้นcontext.strokeStyle
: เอาไว้กำหนดสีของเส้นcontext.lineCap
: กำหนดรูปแบบของเส้น เช่นround
,square
หรือbutt
ตัวอย่าง เช่น
var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')
context.beginPath()context.strokeStyle = '#3984dd'context.lineWidth = 10context.moveTo(50, 50)context.lineTo(50, 200)context.stroke()
context.beginPath()context.strokeStyle = '#dd0343'context.lineWidth = 10context.lineCap = 'round'context.moveTo(100, 50)context.lineTo(100, 200)context.stroke()
context.beginPath()context.strokeStyle = '#06f3d2'context.lineWidth = 10context.lineCap = 'butt'context.moveTo(150, 50)context.lineTo(150, 200)context.stroke()
See the Pen ZYRorp by Chai Phonbopit (@Phonbopit) on CodePen.
วาด Text
การวาด Text จะมีด้วยกัน 2 เมธอดคือ
fillText(text, x, y)
: คือการแสดง Text แบบปกติstrokeText(text, x, y)
: วาดแต่เส้นขอบของ Text
และเมธอดสำคัญๆ อื่นๆด้วย เช่น
font
: ทำการกำหนดขนาดและฟ้อนที่ต้องการใช้fillStyle
: ไว้กำหนดสีของ Text แบบเดียวกันกับการวาดสี่เหลี่ยม วงกลม เส้นtextAlign
: สามารถกำหนดtext-align
ได้
ดังเช่นตัวอย่าง
var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')
context.beginPath()context.font = '50px Open Sans sans-serif'context.fillStyle = '#f36'context.fillText('Hello HTML5 Canvas', 50, 50)
See the Pen EaRLEX by Chai Phonbopit (@Phonbopit) on CodePen.
ประยุกต์ใช้ Canvas แบบง่ายๆ
ตัวอย่างผมจะลองสร้าง ลูกบอล จากนั้นก็ให้มันเด้ง อยู่ภายใน canvas
เริ่มแรกผมสร้างลูกบอลขึ้นมา โดยกำหนด x, y, radius, speedX, speedY ต่างๆ เพื่อกำหนดตำแหน่งลูกบอล รัศมี ความเร็วบอลในแกน x,y ดังนี้
var ball = { x: 20, y: 200, radius: 20, speedX: 2, speedY: 4}
จากนั้นก็ใช้ฟังค์ชั่น context.arc()
เพื่อวาดวงกลมลงไป แต่มันจะไม่ขยับ ก็เลยต้องใช้ setInterval()
เพื่อให้มัน refresh ทุกๆ 1000/60 millisec (60 FPS)
setInterval(functino() { update(); render();}, 1000 / 60);
จากนั้นผมสร้างฟังค์ชัน update()
เพื่อเอาไว้วาดวงกลมทุกๆครั้งที่ถูกรีเฟรซ จุดประสงค์คือทุกครั้งที่รีเฟรซก็จะทำการขยับตำแหน่ง ball จะได้ดังนี้
ball.x += ball.speedXball.y += ball.speedY
เมื่อลองรันดูจะพบผลลัพธ์ดังนี้ (ลูกบอลทั้งหมดไม่ถูกลบ แต่จะซ้อนทับกันไปเรื่อยๆ)
See the Pen MYXGBj by Chai Phonbopit (@Phonbopit) on CodePen.
ฉะนั้นก็เลยต้องทำการเคลียร์ canvas
ก่อนทุกครั้ง
canvas.width = canvas.width // reset canvasball.x += ball.speedXball.y += ball.speedY
Note: Clear Canvas ง่ายๆด้วย
canvas.width = canvas.width;
ซึ่งจริงๆจะใช้clearRect(0, 0, canvas.width, canvas.height)
ก็ได้
ต่อมา render()
ผมเอาไว้แสดงผลลูกบอล (update()
เอาไว้เปลี่ยนแปลง x,y เฉยๆ ไม่ได้วาด)
function render() { context.fillStyle = '#2634dd' context.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2) context.fill()}
สุดท้ายกำหนดเงื่อนไข ถ้าลูกบอลเด้งไปโดนขอบ แต่ละด้าน ให้มันเด้งกลับ (ใช้ speed *= -1
)
ดังนี้
if (ball.x > canvas.width - ball.radius || ball.x < ball.radius) { ball.speedX *= -1}
if (ball.y > canvas.height - ball.radius || ball.y < ball.radius) { ball.speedY *= -1}
ball.x += ball.speedXball.y += ball.speedY
สุดท้ายโค๊ดทั้งหมด และตัวอย่างเดโม่
var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')
var ball = { x: 20, y: 200, radius: 20, speedX: 2, speedY: 4}
start()
function start() { setInterval(function () { update() render() }, 1000 / 60)}
function update() { canvas.width = canvas.width // reset canvas
if (ball.x > canvas.width - ball.radius || ball.x < ball.radius) { ball.speedX *= -1 }
if (ball.y > canvas.height - ball.radius || ball.y < ball.radius) { ball.speedY *= -1 }
ball.x += ball.speedX ball.y += ball.speedY}
function render() { context.fillStyle = '#2634dd' context.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2) context.fill()}
See the Pen RNJyJq by Chai Phonbopit (@Phonbopit) on CodePen.
สรุป
บทความนี้ก็เป็นการนำเสนอ HTML5 Canvas แบบง่ายๆสำหรับผู้เริ่มต้น ในแบบฉบับของผมนะครับ ซึ่งผมก็เพิ่งจะนั่งศึกษา นั่งอ่าน ตามเว็บและบล็อกดังที่แนบไว้ใน References หากผิดพลาดไปบ้าง ก็ขออภัยด้วยครับ
สุดท้ายรายชื่อด้านล่างก็เป็นรายการที่ผมลิสท์ไว้ ดูแล้วน่าสนใจ ว่าจะเอาไว้อ่านต่อ และ Reference ทั้งๆหมดที่ใช้อ้างอิง หากใครสนใจอ่านเพิ่มเติมก็สามารถเข้าไปดูได้ครับ
References
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust