การใช้ HTML5 Canvas: การวาดรูปทรงพื้นฐาน
ในบทนี้ เราจะมาสำรวจอีกหนึ่งความสามารถที่น่าสนใจของ HTML5 นั่นคือ <canvas> element ซึ่งเป็นพื้นที่สี่เหลี่ยมผืนผ้าที่เราสามารถใช้ JavaScript วาดรูปภาพ กราฟ หรือแม้กระทั่งสร้างเกมแบบง่ายๆ ได้ ในบทนี้ เราจะเน้นไปที่การวาดรูปทรงพื้นฐาน เช่น สี่เหลี่ยม วงกลม และเส้นตรง ซึ่งเป็นพื้นฐานสำคัญในการสร้างภาพที่ซับซ้อนยิ่งขึ้น
ทำความรู้จักกับ <canvas> Element
<canvas> element เป็นเหมือนผืนผ้าใบเปล่าๆ ที่รอให้เราใช้สีและพู่กัน (ในที่นี้คือ JavaScript) แต่งแต้มลงไป การใช้งานนั้นง่ายมาก เพียงแค่เพิ่ม tag <canvas> ลงใน HTML ของเรา:
<canvas id="myCanvas" width="500" height="300"></canvas>
สิ่งที่ควรสังเกตคือ attribute width และ height ซึ่งกำหนดขนาดของ canvas ในหน่วย pixels การกำหนดขนาดที่นี่มีความสำคัญ เพราะมันจะส่งผลต่อความละเอียดของภาพที่เราวาด หากไม่กำหนดขนาด canvas จะมีขนาดเริ่มต้นที่เล็กมาก (300x150 pixels) และอาจทำให้ภาพที่เราวาดดูไม่คมชัด
เหตุผลเชิงออกแบบ: ทำไมเราต้องกำหนดขนาด canvas ใน HTML และไม่ใช้ CSS? แม้ว่าเราจะสามารถกำหนดขนาด canvas ด้วย CSS ได้ แต่การทำเช่นนั้นจะทำให้ภาพที่เราวาดถูกปรับขนาด (scaled) ตาม CSS ที่กำหนด ซึ่งอาจทำให้ภาพดูเบลอหรือไม่คมชัด การกำหนดขนาดใน HTML จะทำให้มั่นใจได้ว่าเรากำลังวาดบน canvas ที่มีขนาดที่เราต้องการจริงๆ
การเข้าถึง Canvas Element ใน JavaScript
เมื่อเรามี canvas ใน HTML แล้ว สิ่งที่เราต้องทำต่อไปคือการเข้าถึง canvas element ใน JavaScript เพื่อให้เราสามารถวาดรูปทรงต่างๆ ลงไปได้ เราสามารถทำได้โดยใช้ document.getElementById():
const canvas = document.getElementById("myCanvas");
จากนั้น เราต้องดึง "context" ของ canvas ซึ่งเป็น object ที่มี methods สำหรับการวาดรูปทรงต่างๆ Context ที่เราจะใช้ในบทนี้คือ "2d context" ซึ่งเหมาะสำหรับการวาดภาพสองมิติ:
const ctx = canvas.getContext("2d");
ctx คือตัวแปรที่เราจะใช้ในการเรียก methods ต่างๆ เพื่อวาดรูปทรง
การวาดรูปทรงด้วย Context Methods
ตอนนี้เราพร้อมที่จะเริ่มวาดรูปทรงต่างๆ แล้ว เราจะเริ่มจากรูปสี่เหลี่ยม ซึ่งมีสองวิธีในการวาด:
fillRect(x, y, width, height): วาดสี่เหลี่ยมที่เติมสีstrokeRect(x, y, width, height): วาดสี่เหลี่ยมที่เป็นเส้นขอบ
x และ y คือพิกัดของมุมบนซ้ายของสี่เหลี่ยม ส่วน width และ height คือความกว้างและความสูงของสี่เหลี่ยม
// วาดสี่เหลี่ยมที่เติมสีแดง
ctx.fillStyle = "red";
ctx.fillRect(10, 10, 100, 50);
// วาดสี่เหลี่ยมที่เป็นเส้นขอบสีน้ำเงิน
ctx.strokeStyle = "blue";
ctx.strokeRect(150, 10, 100, 50);
เหตุผลเชิงออกแบบ: ทำไมต้องมีทั้ง fillRect และ strokeRect? การมีทั้งสอง methods ช่วยให้เรามีความยืดหยุ่นในการสร้างสี่เหลี่ยมที่มีลักษณะแตกต่างกัน เราสามารถเลือกที่จะเติมสีสี่เหลี่ยม หรือจะวาดแค่เส้นขอบก็ได้ ขึ้นอยู่กับความต้องการของเรา
ต่อมา เราจะมาดูวิธีการวาดวงกลม (หรือวงรี) โดยใช้ method arc(x, y, radius, startAngle, endAngle, anticlockwise):
xและyคือพิกัดของจุดศูนย์กลางของวงกลมradiusคือรัศมีของวงกลมstartAngleคือมุมเริ่มต้นของการวาดวงกลม (ในหน่วย radians)endAngleคือมุมสิ้นสุดของการวาดวงกลม (ในหน่วย radians)anticlockwiseคือ boolean ที่ระบุว่าเราจะวาดวงกลมในทิศทางทวนเข็มนาฬิกาหรือไม่ (ค่าเริ่มต้นคือfalseซึ่งหมายถึงตามเข็มนาฬิกา)
ในการวาดวงกลมเต็มวง เราจะใช้ startAngle เป็น 0 และ endAngle เป็น 2 * Math.PI (2π radians):
// วาดวงกลมที่เติมสีเขียว
ctx.beginPath(); // เริ่มต้น path ใหม่
ctx.arc(300, 40, 30, 0, 2 * Math.PI);
ctx.fillStyle = "green";
ctx.fill();
// วาดวงกลมที่เป็นเส้นขอบสีดำ
ctx.beginPath(); // เริ่มต้น path ใหม่
ctx.arc(400, 40, 30, 0, 2 * Math.PI);
ctx.strokeStyle = "black";
ctx.stroke();
ข้อควรระวัง: ก่อนที่จะวาดวงกลม (หรือรูปทรงอื่นๆ ที่ซับซ้อน) เราต้องเรียก beginPath() ก่อนเสมอ เพื่อบอกให้ canvas รู้ว่าเรากำลังจะเริ่มวาด path ใหม่ หากไม่ทำเช่นนั้น การวาดรูปทรงใหม่จะถูกเชื่อมต่อกับรูปทรงเก่า ทำให้เกิดผลลัพธ์ที่ไม่คาดคิด
สุดท้าย เราจะมาดูวิธีการวาดเส้นตรง โดยใช้ methods moveTo(x, y) และ lineTo(x, y):
moveTo(x, y): กำหนดจุดเริ่มต้นของเส้นlineTo(x, y): วาดเส้นจากจุดเริ่มต้นไปยังพิกัด (x, y)
// วาดเส้นสีม่วง
ctx.beginPath(); // เริ่มต้น path ใหม่
ctx.moveTo(10, 100); // กำหนดจุดเริ่มต้น
ctx.lineTo(200, 150); // วาดเส้นไปยังจุด (200, 150)
ctx.strokeStyle = "purple";
ctx.lineWidth = 5; // กำหนดความหนาของเส้น
ctx.stroke();
เราสามารถกำหนดความหนาของเส้นได้โดยใช้ lineWidth และเราสามารถวาดเส้นหลายเส้นต่อเนื่องกันได้ โดยไม่ต้องเรียก moveTo() ใหม่
แนวปฏิบัติที่ดี: ควรเรียก beginPath() ก่อนเริ่มวาดรูปทรงใหม่เสมอ เพื่อป้องกันผลลัพธ์ที่ไม่คาดคิดจากการเชื่อมต่อ path เก่ากับ path ใหม่ นอกจากนี้ ควรตั้งค่าสีและสไตล์ก่อนที่จะเรียก methods สำหรับการวาดรูปทรง เพื่อให้โค้ดอ่านง่ายและเข้าใจได้ง่ายขึ้น
การกำหนดสีและสไตล์ให้กับรูปทรง
เราได้เห็นวิธีการกำหนดสีให้กับรูปทรงไปแล้วบ้าง แต่เราจะมาลงรายละเอียดเพิ่มเติมเกี่ยวกับ properties ที่เกี่ยวข้องกับการกำหนดสีและสไตล์:
fillStyle: กำหนดสีสำหรับเติมสีรูปทรง (เช่น สี่เหลี่ยม วงกลม)strokeStyle: กำหนดสีสำหรับเส้นขอบรูปทรงlineWidth: กำหนดความหนาของเส้นขอบ (ในหน่วย pixels)lineCap: กำหนดลักษณะของปลายเส้น (เช่นbutt,round,square)lineJoin: กำหนดลักษณะของจุดเชื่อมต่อระหว่างเส้น (เช่นbevel,round,miter)
ค่าสีที่เราสามารถกำหนดให้กับ fillStyle และ strokeStyle มีหลายรูปแบบ เช่น:
- ชื่อสี (เช่น "red", "blue", "green")
- ค่า hexadecimal (เช่น "#FF0000", "#0000FF", "#00FF00")
- ค่า RGB (เช่น "rgb(255, 0, 0)", "rgb(0, 0, 255)", "rgb(0, 255, 0)")
- ค่า RGBA (เช่น "rgba(255, 0, 0, 0.5)", "rgba(0, 0, 255, 0.5)", "rgba(0, 255, 0, 0.5)")
ค่า RGBA จะมี alpha channel เพิ่มเข้ามา ซึ่งกำหนดความโปร่งแสงของสี โดยค่า alpha จะอยู่ในช่วง 0 (โปร่งใส) ถึง 1 (ทึบแสง)
// วาดสี่เหลี่ยมที่เติมสีแดงโปร่งแสง
ctx.fillStyle = "rgba(255, 0, 0, 0.5)";
ctx.fillRect(10, 200, 100, 50);
// วาดเส้นสีน้ำเงินที่มีปลายเส้นโค้งมน
ctx.beginPath();
ctx.moveTo(150, 200);
ctx.lineTo(300, 250);
ctx.strokeStyle = "blue";
ctx.lineWidth = 10;
ctx.lineCap = "round";
ctx.stroke();
สรุป
ในบทนี้ เราได้เรียนรู้พื้นฐานของการใช้งาน HTML5 Canvas โดยเริ่มต้นจากการสร้าง canvas element ใน HTML การเข้าถึง canvas context ใน JavaScript และการวาดรูปทรงพื้นฐาน เช่น สี่เหลี่ยม วงกลม และเส้นตรง นอกจากนี้ เรายังได้เรียนรู้วิธีการกำหนดสีและสไตล์ให้กับรูปทรงต่างๆ ความรู้เหล่านี้เป็นพื้นฐานสำคัญในการสร้างภาพที่ซับซ้อนยิ่งขึ้นบน canvas ในบทต่อไป เราจะมาเรียนรู้เกี่ยวกับการจัดการรูปภาพบน canvas และการสร้างภาพเคลื่อนไหวแบบง่ายๆ