มาเรียน Canvas ผ่าน Pong game กัน
/ 4 min read
html , canvas , animation , javascript , pong game , drawing , game development , requestanimationframe
สามารถดู video ของหัวข้อนี้ก่อนได้ ดู video
มาเรียนรู้ canvas ผ่านการสร้าง Pong game กัน ว่า
- animation ที่เคลื่อนได้บน canvas ทำได้ยังไง
- ตำแหน่งบน canvas ดูยังไง
- เราทำอะไรบน canvas ได้บ้าง
Canvas คืออะไร ?
Ref: https://www.w3schools.com/html/html5_canvas.asp
Canvas เป็น feature ด้านกราฟฟิคที่เตรียมมาไว้ใน HTML5 ที่สามารถทำให้เรา “วาดภาพ” บน html ได้ (ตามชื่อของมันเลยคือ ผ้าใบที่วาดภาพได้)
<canvas width="200" height="100"></canvas>
วาดของบน Canvas ได้ยังไง ?
คำสั่ง Javascript นั้นสามารถ access เข้าถึง Canvas และสามารถวาดลงไปบน Canvas ได้ มันก็จะมีตั้งแต่
- วาดเส้น
const ctx = canvas.getContext("2d");ctx.moveTo(0, 0);ctx.lineTo(200, 100);ctx.stroke();
- วาดวงกลม
const ctx = canvas.getContext("2d");ctx.beginPath();ctx.arc(95, 50, 40, 0, 2 * Math.PI);ctx.stroke();
- วาดสี่เหลี่ยม
const ctx = canvas.getContext("2d");
// Filled Rectanglectx.fillStyle = "blue";ctx.fillRect(10, 10, 100, 50);
// Stroked Rectanglectx.strokeStyle = "red";ctx.strokeRect(120, 10, 100, 50);
// Clear a section of the canvasctx.clearRect(50, 30, 30, 20);
- วาดเส้นโค้ง
const ctx = canvas.getContext("2d");
// Elliptical arc using quadratic curvesctx.beginPath();ctx.moveTo(300, 100);ctx.quadraticCurveTo(350, 50, 400, 100);ctx.quadraticCurveTo(350, 150, 300, 100);ctx.fillStyle = "purple";ctx.fill();
- ลงตัวอักษร
const ctx = canvas.getContext("2d");ctx.font = "30px Arial";ctx.fillText("Hello World", 10, 50);
- ลงสี
// Create gradientconst ctx = canvas.getContext("2d");const grd = ctx.createLinearGradient(0, 0, 200, 0);grd.addColorStop(0, "red");grd.addColorStop(1, "white");
// Fill with gradientctx.fillStyle = grd;ctx.fillRect(10, 10, 150, 80);
- ลงรูป
const ctx = canvas.getContext("2d");// access ไปยังรูปconst img = document.getElementById("scream");// วาดรูปลง canvasctx.drawImage(img, 10, 10);
Animation ใน canvas เกิดขึ้นได้ยังไง ?
คำสั่งที่ทำให้เราสามารถวาดได้คือ requestAnimationFrame()
- canvas ฮิตมากสำหรับใช้คู่กับการทำ Animation (มันให้อารมณ์วาดการตูนบนแผ่นกระดาษแล้วซ้อน frame กัน)
- คำสั่ง
requestAnimationFrame()
คือคำสั่งสำหรับการทำ loop คำสั่งแบบ 60 fps (60 execute ใน 1 วินาที) - ดีกว่า setInterval ตรงที่มันจะ “ไม่” ทำงานเมื่อไม่อยู่ใน tab อื่น = ประหยัดการทำงานมากกว่า
มาลองทำ Pong game กัน
สิ่งที่เราจะทำ
- ปู canvas ออกมา
- สร้าง paddle (แผ่นตี pong game) และ ลูกปิงปองขึ้นมา
- สร้างให้ปิงปองและ cpu paddle เคลื่อนไหวได้ด้วย
requestAnimationFrame()
- สร้าง การชนของ paddle ออกมา เพื่อให้เกิดการเด้งกลับ
- ทำให้ paddle ตัวเองให้เคลื่อนไหวด้วย เมาส์
= เราก็จะได้ pong game หน้าตาแบบนี้ออกมา

เรามาเริ่มทำกันในแต่ละ step
สร้าง canvas และ selector ออกมาก่อน
!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Pong Game</title> <style> canvas { background-color: #000 display: block margin: 0 auto } </style> </head> <body> <canvas id="pong" width="800" height="400"></canvas>
<script> const canvas = document.getElementById("pong"); const ctx = canvas.getContext("2d");
/* ที่เหลือเราจะมาใส่ code ตรงนี้กัน */ </script> </body></html>
สร้าง paddle (แผ่นตี pong game) และ ลูกปิงปองขึ้นมา
<script> // สร้าง canvas ball const ball = { x: canvas.width / 2, y: canvas.height / 2, radius: 10, speed: 4, dx: 4, dy: 4, color: "WHITE", };
// สร้าง canvas ฝั่ง user const userPaddle = { x: 0, y: canvas.height / 2 - 40, width: 10, height: 80, dy: 4, color: "WHITE", };
// สร้าง canvas ฝั่ง computer const compPaddle = { x: canvas.width - 10, y: canvas.height / 2 - 40, width: 10, height: 80, dy: 4, color: "WHITE", };
function drawRect(x, y, width, height, color) { ctx.fillStyle = color; ctx.fillRect(x, y, width, height); }
function drawCircle(x, y, radius, color) { ctx.fillStyle = color; ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI * 2, false); ctx.closePath(); ctx.fill(); }
// ทำการวาดออกมา function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawRect(userPaddle.x, userPaddle.y, userPaddle.width, userPaddle.height, userPaddle.color); drawRect(compPaddle.x, compPaddle.y, compPaddle.width, compPaddle.height, compPaddle.color); drawCircle(ball.x, ball.y, ball.radius, ball.color); }
function game() { draw(); }
// run game game();</script>
สร้างให้ปิงปองและ cpu paddle เคลื่อนไหวได้ด้วย requestAnimationFrame()
<script> function update() { // ทำให้บอลเคลื่อนไหวไปเรื่อยๆ ball.x += ball.dx; ball.y += ball.dy;
// ออกนอกกรอบ canvas = เปลี่ยนเส้นทาง if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) { ball.dy = -ball.dy; }
if (ball.x + ball.radius > canvas.width) { // กระทบ paddle cpu if (ball.y > compPaddle.y && ball.y < compPaddle.y + compPaddle.height) { ball.dx = -ball.dx; } else { // ออกจอไป = reset ลูกใหม่ ball.x = canvas.width / 2; ball.y = canvas.height / 2; // และเปลี่ยนทิศทาง ball.dx = -ball.dx; } }
if (ball.x - ball.radius < 0) { // กระทบ paddle ฝั่ง user if (ball.y > userPaddle.y && ball.y < userPaddle.y + userPaddle.height) { ball.dx = -ball.dx; } else { // ออกนอกจอไป = reset ใหม่ ball.x = canvas.width / 2; ball.y = canvas.height / 2; } }
// สุ่มการเคลื่อนไหวของ paddle compPaddle.y += (ball.y - (compPaddle.y + compPaddle.height / 2)) * 0.09; }
function game() { // เพิ่มการเคลื่อนไหว update(); draw(); // เพิ่มการเรียกในแต่ละ frame requestAnimationFrame(game); }
// run game game();</script>
ทำให้ paddle ตัวเองให้เคลื่อนไหวด้วย เมาส์
<script> // เพิ่มการเคลื่อนไหว canvas ด้วยเมาส์ canvas.addEventListener("mousemove", (event) => { const rect = canvas.getBoundingClientRect(); userPaddle.y = event.clientY - rect.top - userPaddle.height / 2; });</script>
ปกติ canvas ใช้ทำอะไรบ้าง
- Drawing Applications ใช้ทำพวก image editor, stecth pad (คล้ายๆกับพวก Microsoft Paint) ** พวก web app อะไรก็ตามที่ต้องอาศัยการจัดการ UI แบบ Custom = จะใช้พวก canvas นี่แหละ ช่วยได้
- Games อย่างที่เห็น เมื่อใช้ Canvas ผสมกับการ render animation = สามารถที่จะ render graphic ที่มี animation ได้ มันเลยกลายเป็น base ของการทำ game ได้
- Animations ใช้ทำพวก animation ร่วมกับ user input ได้ (เช่นเคสการเล่นกับเมาส์, การคลิก)
- Photo Manipulation ใช้ร่วมกับการจัดการภาพ ภาพมันสามารถนำมาแสดงผลบน canvas และ สามารถแทรก filter, ปรับสีและสามารถใช้ effect ร่วมกับภาพบน canvas ได้
อะไรก็ตามที่อาศัยการวาด, การทำ animation และการจัดการกับ Event ของ User = Canvas สามารถช่วยคุณได้
Related Post
- LLM Local and APIมี Video
แนะนำพื้นฐาน LLM การใช้งานบน Local ด้วย LM Studio และ Ollama พร้อมตัวอย่างการสร้าง API ด้วย FastAPI และการใช้งานร่วมกับ Continue AI
- มาแก้ปัญหา Firestore กับปัญหาราคา Read pricing สุดจี๊ดมี Video มี Github
ในฐานะที่เป็นผู้ใช้ Firebase เหมือนกัน เรามาลองชวนคุยกันดีกว่า ว่าเราจะสามารถหาวิธีลด Pricing หรือจำนวนการ read ของ Firestore ได้ยังไงกันบ้าง
- มารู้จัก Svelte และ SvelteKit กันมี Video มี Github
สำรวจโลกแห่งการพัฒนาเว็บไซต์สมัยใหม่ด้วยการแนะนำ Svelte และ SvelteKit ที่ครอบคลุมของเรา
- มาเรียนรู้พื้นฐาน Diagram แต่ละประเภทของงาน development กันมี Video
รู้จักกับ Diagram ที่ใช้บ่อยประเภทต่างๆว่ามีอะไรบ้าง และใช้สำหรับทำอะไรบ้าง