Devahoy Logo
PublishedAt

Web Development

HTML5 Canvas คืออะไร? + วิธีใช้งานเบื้องต้น

HTML5 Canvas คืออะไร? + วิธีใช้งานเบื้องต้น

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> นะครับ :)

ตัวอย่างเช่น

1
<canvas id="tutorial" width="150" height="150"></canvas>

เป็นการประกาศสร้าง Element <canvas> ขึ้นมาโดยมี id ชื่อ canvas และมีความกว้างและความสูง 150 pixels

Note: โดยปกติแล้ว canvas จะมีความกว้าง 300px และสูง 150px ถึงแม้ว่าเราจะไม่ได้กำหนดขนาดให้มันก็ตาม

ใช้งาน Canvas เบื้องต้น

เริ่มแรกทำการสร้างไฟล์ HTML ขึ้นมา ผมทำการตั้งชื่อว่า index.html และมี element <canvas> ดังตัวอย่าง

1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8" />
5
<title>HTML5 Canvas Tutorials</title>
6
</head>
7
<body>
8
<canvas id="canvas" width="500" height="500"></canvas>
9
10
<script src="main.js"></script>
11
</body>
12
</html>

จากนั้นลิงค์สคริปไปยังไฟล์ JavaScript ของเรา โดยทำการตั้งชื่อว่า main.js

1
var canvas = document.getElementById('canvas')
2
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 ดังตัวอย่างเปรียบเทียบในภาพด้านล่างครับ

Canvas System

วาดสี่เหลี่ยม

การวาดสี่เหลี่ยม สามารถใช้ฟังค์ชัน fillRect(x, y, width, height) โดย x คือแกน x, y คือแกน y และ width, height คือความกว้างและความสูง ตามลำดับ

โดยเมื่อเราเลือก Element canvas และทำการ getContext() แล้ว เราสามารถวาดสี่เหลี่ยมแบบง่ายๆ ด้วยโค๊ดแบบนี้

1
// กำหนดสี
2
context.fillStyle = 'green'
3
// วาดสี่เหลี่ยม Rectangle (x, y, width, height)
4
// โดยแกน x,y จะนับจากมุมบนซ้ายเป็นจุด 0, 0
5
context.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 อื่นๆ (เหมือนเป็นยางลบ)

เช่น

1
var canvas = document.getElementById('canvas')
2
var context = canvas.getContext('2d')
3
4
context.fillStyle = 'green'
5
context.fillRect(10, 10, 100, 100)
6
7
context.strokeStyle = 'red'
8
context.strokeRect(110, 110, 200, 200)
9
10
context.clearRect(35, 35, 50, 50)

See the Pen jEKxGO by Chai Phonbopit (@Phonbopit) on CodePen.

Paths

ให้นึกถึงเวลาคุณจับดินสอวาดรูป Path หนึ่งก็เหมือนกับการจิ้มดินสอลงบนกระดาษ เวลาคุณวาดรูป คุณก็จะมีการยกดินสอขึ้น และเลื่อนไปยังอีกตำแหน่งเพื่อวาดภาพต่อๆมา (ลองนึกว่าให้คุณวาดรูปแมวโดยไม่ยกดินสอซิ เปรียบเสมือนใช้ Canvas แค่ Path เดียว)

ฉะนั้น Path จะมีด้วยกัน 2 เมธอดคือ (ให้นึกถึงการใช้ดินสอวาดรูปเหมือนเดิม)

  1. moveTo(x, y) : หมายถึงเลื่อนดินสอไปยังตำแหน่งที่ต้องการ (จุดเริ่มต้น)
  2. lineTo(x, y) : หมายถึงว่าลากเส้นไปถึงตำแหน่งไหน (จุดสุดท้ายที่ยกมือ)

เช่น

1
context.moveTo(0, 100)
2
context.lineTo(200, 100)

แต่ว่ายังไม่มีอะไรเกิดขึ้น เนื่องจากว่าดินสอเราไส้หมดครับ ต้องเดิมไส้ใหม่ พอดีใช้ดินสอกด :)

1
context.strokeStyle = 'black';
2
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 และวาดทั้งวงกลม จะได้ดังนี้

1
var canvas = document.getElementById('canvas')
2
var context = canvas.getContext('2d')
3
4
context.beginPath()
5
context.strokeStyle = 'black'
6
context.lineWidth = 5
7
context.arc(50, 50, 40, 0, Math.PI * 2, false)
8
context.stroke()
9
context.closePath()
10
11
context.beginPath()
12
context.fillStyle = '#dd0343'
13
context.arc(120, 120, 40, 0, Math.PI * 2)
14
context.fill()
15
context.closePath()

See the Pen GgGdOw by Chai Phonbopit (@Phonbopit) on CodePen.

วาดเส้น

การวาดเส้นบน Canvas เราจะใช้ร่วมกับการใช้ Path โดยมีฟังค์ชันที่สำคัญดังนี้

  • context.beginPath() : สำหรับกำหนด path
  • context.moveTo(x, y) : ตำแหน่งเริ่มต้นในการวาด
  • context.lineTo(x, y) : ตำแหน่งสิ้นสุดการวาด
  • context.lineWidth : เอาไว้กำหนดขนาดของเส้น
  • context.strokeStyle : เอาไว้กำหนดสีของเส้น
  • context.lineCap : กำหนดรูปแบบของเส้น เช่น round, square หรือ butt

ตัวอย่าง เช่น

1
var canvas = document.getElementById('canvas')
2
var context = canvas.getContext('2d')
3
4
context.beginPath()
5
context.strokeStyle = '#3984dd'
6
context.lineWidth = 10
7
context.moveTo(50, 50)
8
context.lineTo(50, 200)
9
context.stroke()
10
11
context.beginPath()
12
context.strokeStyle = '#dd0343'
13
context.lineWidth = 10
14
context.lineCap = 'round'
15
context.moveTo(100, 50)
16
context.lineTo(100, 200)
17
context.stroke()
18
19
context.beginPath()
20
context.strokeStyle = '#06f3d2'
21
context.lineWidth = 10
22
context.lineCap = 'butt'
23
context.moveTo(150, 50)
24
context.lineTo(150, 200)
25
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 ได้

ดังเช่นตัวอย่าง

1
var canvas = document.getElementById('canvas')
2
var context = canvas.getContext('2d')
3
4
context.beginPath()
5
context.font = '50px Open Sans sans-serif'
6
context.fillStyle = '#f36'
7
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 ดังนี้

1
var ball = {
2
x: 20,
3
y: 200,
4
radius: 20,
5
speedX: 2,
6
speedY: 4
7
}

จากนั้นก็ใช้ฟังค์ชั่น context.arc() เพื่อวาดวงกลมลงไป แต่มันจะไม่ขยับ ก็เลยต้องใช้ setInterval() เพื่อให้มัน refresh ทุกๆ 1000/60 millisec (60 FPS)

1
setInterval(functino() {
2
update();
3
render();
4
}, 1000 / 60);

จากนั้นผมสร้างฟังค์ชัน update() เพื่อเอาไว้วาดวงกลมทุกๆครั้งที่ถูกรีเฟรซ จุดประสงค์คือทุกครั้งที่รีเฟรซก็จะทำการขยับตำแหน่ง ball จะได้ดังนี้

1
ball.x += ball.speedX
2
ball.y += ball.speedY

เมื่อลองรันดูจะพบผลลัพธ์ดังนี้ (ลูกบอลทั้งหมดไม่ถูกลบ แต่จะซ้อนทับกันไปเรื่อยๆ)

See the Pen MYXGBj by Chai Phonbopit (@Phonbopit) on CodePen.

ฉะนั้นก็เลยต้องทำการเคลียร์ canvas ก่อนทุกครั้ง

1
canvas.width = canvas.width // reset canvas
2
ball.x += ball.speedX
3
ball.y += ball.speedY

Note: Clear Canvas ง่ายๆด้วย canvas.width = canvas.width; ซึ่งจริงๆจะใช้ clearRect(0, 0, canvas.width, canvas.height) ก็ได้

ต่อมา render() ผมเอาไว้แสดงผลลูกบอล (update() เอาไว้เปลี่ยนแปลง x,y เฉยๆ ไม่ได้วาด)

1
function render() {
2
context.fillStyle = '#2634dd'
3
context.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2)
4
context.fill()
5
}

สุดท้ายกำหนดเงื่อนไข ถ้าลูกบอลเด้งไปโดนขอบ แต่ละด้าน ให้มันเด้งกลับ (ใช้ speed *= -1)

ดังนี้

1
if (ball.x > canvas.width - ball.radius || ball.x < ball.radius) {
2
ball.speedX *= -1
3
}
4
5
if (ball.y > canvas.height - ball.radius || ball.y < ball.radius) {
6
ball.speedY *= -1
7
}
8
9
ball.x += ball.speedX
10
ball.y += ball.speedY

สุดท้ายโค๊ดทั้งหมด และตัวอย่างเดโม่

1
var canvas = document.getElementById('canvas')
2
var context = canvas.getContext('2d')
3
4
var ball = {
5
x: 20,
6
y: 200,
7
radius: 20,
8
speedX: 2,
9
speedY: 4
10
}
11
12
start()
13
14
function start() {
15
setInterval(function () {
16
update()
17
render()
18
}, 1000 / 60)
19
}
20
21
function update() {
22
canvas.width = canvas.width // reset canvas
23
24
if (ball.x > canvas.width - ball.radius || ball.x < ball.radius) {
25
ball.speedX *= -1
26
}
27
28
if (ball.y > canvas.height - ball.radius || ball.y < ball.radius) {
29
ball.speedY *= -1
30
}
31
32
ball.x += ball.speedX
33
ball.y += ball.speedY
34
}
35
36
function render() {
37
context.fillStyle = '#2634dd'
38
context.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2)
39
context.fill()
40
}

See the Pen RNJyJq by Chai Phonbopit (@Phonbopit) on CodePen.

สรุป

บทความนี้ก็เป็นการนำเสนอ HTML5 Canvas แบบง่ายๆสำหรับผู้เริ่มต้น ในแบบฉบับของผมนะครับ ซึ่งผมก็เพิ่งจะนั่งศึกษา นั่งอ่าน ตามเว็บและบล็อกดังที่แนบไว้ใน References หากผิดพลาดไปบ้าง ก็ขออภัยด้วยครับ

สุดท้ายรายชื่อด้านล่างก็เป็นรายการที่ผมลิสท์ไว้ ดูแล้วน่าสนใจ ว่าจะเอาไว้อ่านต่อ และ Reference ทั้งๆหมดที่ใช้อ้างอิง หากใครสนใจอ่านเพิ่มเติมก็สามารถเข้าไปดูได้ครับ

References

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust

Related Posts