"เป็นคุณเสมอสำหรับ Canvas2D"

อารอน คราเจสกี
อารอน คราเจสกี

ในโลกของการให้เฉดสี ตาข่าย และฟิลเตอร์ Canvas2D อาจไม่ทำให้คุณตื่นเต้น แต่จริงๆ นะ หน้าเว็บ 30-40% มีองค์ประกอบ <canvas> และ Canvas 98% จากทั้งหมดใช้บริบทการแสดงผล Canvas2D มี Canvas2D ในรถ ตู้เย็น และในอวกาศ (จริงๆ นะ)

เป็นที่ยอมรับกันว่า API นั้นอยู่เบื้องหลังการวาดภาพ 2 มิติที่ล้ำสมัยไปเล็กน้อย โชคดีที่เราทุ่มเทอย่างเต็มที่ในการติดตั้งใช้งานฟีเจอร์ใหม่ๆ ใน Canvas2D เพื่อตามให้ทัน CSS, ปรับหลักการยศาสตร์ และปรับปรุงประสิทธิภาพ

ส่วนที่ 1: การติดตามข้อมูล CSS

CSS มีคำสั่งวาด 2-3 คำสั่งที่ขาดหายไปมากจาก Canvas2D ด้วย API ใหม่ เราได้เพิ่มคุณลักษณะที่มีการร้องขอมากที่สุดเข้ามาจำนวนหนึ่ง ได้แก่

สี่เหลี่ยมผืนผ้ามุมมน

สี่เหลี่ยมผืนผ้ามุมมน: หลักสำคัญของอินเทอร์เน็ต การประมวลผล ความปลอดภัย และอารยธรรม

ในความรุนแรงทั้งหมด สี่เหลี่ยมผืนผ้ามุมมนนั้นมีประโยชน์อย่างยิ่ง เช่น ปุ่ม ลูกโป่งแชท ภาพขนาดย่อ ลูกโป่งคำพูด เรามักจะสร้างเป็นสี่เหลี่ยมผืนผ้ามุมมนใน Canvas2D ซึ่งดูไม่เป็นระเบียบเลยทีเดียว

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'magenta';

const top = 10;
const left = 10;
const width = 200;
const height = 100;
const radius = 20;

ctx.beginPath();
ctx.moveTo(left + radius, top);
ctx.lineTo(left + width - radius, top);
ctx.arcTo(left + width, top, left + width, top + radius, radius);
ctx.lineTo(left + width, top + height - radius);
ctx.arcTo(left + width, top + height, left + width - radius, top + height, radius);
ctx.lineTo(left + radius, top + height);
ctx.arcTo(left, top + height, left, top + height - radius, radius);
ctx.lineTo(left, top + radius);
ctx.arcTo(left, top, left + radius, top, radius);
ctx.stroke();

ทั้งหมดนี้จำเป็นสำหรับสี่เหลี่ยมผืนผ้ามุมมนที่เรียบง่ายและเรียบง่าย

สี่เหลี่ยมผืนผ้ามุมมน

เมื่อใช้ API ใหม่ จะมีเมธอด roundRect()

ctx.roundRect(upper, left, width, height, borderRadius);

ดังนั้น สามารถแทนที่รายการข้างต้นทั้งหมดด้วย:

ctx.roundRect(10, 10, 200, 100, 20);

เมธอด ctx.roundRect() ยังรับอาร์เรย์สำหรับอาร์กิวเมนต์ borderRadius ที่มีตัวเลขไม่เกิน 4 ตัว รัศมีเหล่านี้ควบคุมมุมทั้ง 4 มุมของสี่เหลี่ยมผืนผ้ามุมมนด้วยวิธีเดียวกับCSS เช่น

ctx.roundRect(10, 10, 200, 100, [15, 50, 30]);

ดูการสาธิตเพื่อทดลองเล่น

ไล่ระดับสีกรวย

คุณเห็นการไล่ระดับสีแบบเส้นตรง

const gradient = ctx.createLinearGradient(0, 0, 200, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'magenta');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

การไล่ระดับสีแบบเส้นตรง

การไล่ระดับสีแบบรัศมี:

const radialGradient = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(0.5, 'magenta');
radialGradient.addColorStop(1, 'lightblue');

ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

การไล่ระดับสีแบบรัศมี

แล้วการไล่ระดับสีแบบกรวยที่ดีล่ะ

const grad = ctx.createConicGradient(0, 100, 100);

grad.addColorStop(0, 'red');
grad.addColorStop(0.25, 'orange');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.75, 'green');
grad.addColorStop(1, 'blue');

ctx.fillStyle = grad;
ctx.fillRect(0, 0, 200, 200);

การไล่ระดับสีรูปกรวย

ตัวปรับแต่งข้อความ

ความสามารถในการแสดงข้อความของ Canvas2Ds เป็นสิ่งที่อยู่เบื้องหลังอย่างล้นหลาม Chrome ได้เพิ่มแอตทริบิวต์ใหม่หลายรายการ ในการแสดงผลข้อความ Canvas2D ดังนี้

แอตทริบิวต์เหล่านี้ทั้งหมดตรงกับคู่ของ CSS ที่มีชื่อเดียวกัน

ส่วนที่ 2: การปรับเปลี่ยนตามหลักการยศาสตร์

ก่อนหน้านี้คุณสามารถใช้ Canvas2D บางอย่างได้ แต่ก็ไม่จำเป็นที่จะต้องติดตั้งใช้งาน การปรับปรุงคุณภาพของชีวิตสำหรับนักพัฒนาซอฟต์แวร์ JavaScript ที่ต้องการใช้ Canvas2D มีดังนี้

รีเซ็ตบริบท

ผมขออธิบายฟังก์ชันการวาดรูปแบบย้อนยุคแบบตลกๆ ดังต่อไปนี้

draw90sPattern();

รูปแบบย้อนยุคของสามเหลี่ยมและสี่เหลี่ยมจัตุรัส

เยี่ยมเลย เมื่อวาดตามรูปแบบเสร็จแล้ว ก็ต้องล้างพื้นที่ไปวาดอย่างอื่นแทน เดี๋ยวนะ เราจะล้างผ้าใบอีกครั้งได้อย่างไร ใช่เลย! ctx.clearRect() ได้เลย

ctx.clearRect(0, 0, canvas.width, canvas.height);

อ๊ะ... ไม่สำเร็จ ใช่เลย! ฉันต้องรีเซ็ตการเปลี่ยนรูปแบบก่อน

ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ผืนผ้าใบเปล่า

สมบูรณ์แบบ ผืนผ้าใบเปล่าสวยๆ ทีนี้มาเริ่มลากเส้นแนวนอนให้สวย

ctx.moveTo(10, 10);
ctx.lineTo(canvas.width, 10);
ctx.stroke();

เส้นแนวนอนและเส้นทแยงมุม

อ๊าาาา! ยังไม่ถูก! 😡 บรรทัดที่เพิ่มขึ้นมาทำอะไรตรงนี้ดี และทำไมรูปจึงเป็นสีชมพู เรามาตรวจสอบ StackOverflow กัน

canvas.width = canvas.width;

ทำไมเกมนี้ตลกจัง ทำไมการดำเนินการนี้จึงเป็นเรื่องยาก

แต่ไม่มากแล้ว เรามี API ใหม่ที่เรียบง่าย สง่างาม สวยงาม และใช้งานง่าย

ctx.reset();

ขออภัยที่ใช้เวลานานเกินไป

ฟิลเตอร์

ฟิลเตอร์ SVG ก็เหมือนกับโลกใบอื่นๆ ถ้าคุณเพิ่งเริ่มใช้งาน เราขอแนะนำให้อ่าน ศิลปะของฟิลเตอร์ SVG และทำไมมันจึงยอดเยี่ยม ซึ่งจะแสดงศักยภาพอันน่าทึ่งของฟิลเตอร์

ฟิลเตอร์รูปแบบ SVG พร้อมให้ใช้งานใน Canvas2D แล้ว คุณเพียงยินดีที่จะส่งฟิลเตอร์เป็น URL ที่ชี้ไปยังองค์ประกอบตัวกรอง SVG อื่นในหน้าเว็บ ดังนี้

<svg>
  <defs>
    <filter id="svgFilter">
      <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
      <feConvolveMatrix kernelMatrix="-3 0 0 0 0.5 0 0 0 3" />
      <feColorMatrix type="hueRotate" values="90" />
    </filter>
  </defs>
</svg>
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 400;
const ctx = canvas.getContext('2d');
document.body.appendChild(canvas);

ctx.filter = "url('#svgFilter')";
draw90sPattern(ctx);

ซึ่งทำให้รูปแบบของเราใช้ไม่ได้

ใช้รูปแบบย้อนยุคที่ใช้เอฟเฟกต์เบลอ

แต่หากต้องการดำเนินการข้างต้น แต่ให้อยู่ภายใน JavaScript และไม่ยุ่งเหยิงกับสตริง ทุกอย่างเป็นไปได้ด้วย API ใหม่

ctx.filter = new CanvasFilter([
  { filter: 'gaussianBlur', stdDeviation: 5 },
  {
    filter: 'convolveMatrix',
    kernelMatrix: [
      [-3, 0, 0],
      [0, 0.5, 0],
      [0, 0, 3],
    ],
  },
  { filter: 'colorMatrix', type: 'hueRotate', values: 90 },
]);

ง่ายเหมือนพาย! ลองใช้งานและลองใช้พารามิเตอร์ ในการสาธิตที่นี่

ส่วนที่ 3: การปรับปรุงประสิทธิภาพ

นอกจากนี้ เรายังต้องการปรับปรุงประสิทธิภาพเมื่อเป็นไปได้ด้วย Canvas2D API ใหม่ เราเพิ่มคุณลักษณะ 2 อย่างเพื่อให้นักพัฒนาซอฟต์แวร์ควบคุมเว็บไซต์ได้ละเอียดยิ่งขึ้น และสามารถใช้อัตราเฟรมที่ราบรื่นที่สุดเท่าที่จะทำได้

จะอ่านบ่อยๆ

ใช้ getImageData() เพื่ออ่านข้อมูลพิกเซลกลับมาจาก Canvas ซึ่งอาจช้ามาก API ใหม่ช่วยให้มีวิธีทำเครื่องหมายอย่างชัดแจ้งเพื่อให้อ่านย้อนกลับได้ (เช่น สำหรับเอฟเฟกต์ Generative) วิธีนี้ช่วยให้คุณเพิ่มประสิทธิภาพการทำงานเบื้องหลังและให้ Canvas ทำงานได้รวดเร็วสำหรับกรณีการใช้งานที่หลากหลายมากขึ้น ฟีเจอร์นี้อยู่ใน Firefox มาสักพักแล้วและสุดท้ายเราก็จะทำให้เป็นส่วนหนึ่งของข้อมูลจำเพาะของ Canvas

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });

การสูญเสียบริบท

มาทำให้แท็บเศร้ากลับมามีความสุขอีกครั้งกันเถอะ! ในกรณีที่หน่วยความจำ GPU เต็มหรือเกิดความเสียหายอื่นๆ เกิดขึ้นกับ Canvas คุณสามารถเรียกกลับและเขียนใหม่ได้ตามต้องการ

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

canvas.addEventListener('contextlost', onContextLost);
canvas.addEventListener('contextrestored', redraw);

ถ้าต้องการอ่านเพิ่มเติมเกี่ยวกับบริบทและการสูญเสียแคนวาส WHATWG มีคำอธิบายดีๆ บน wiki

บทสรุป

ไม่ว่าคุณจะใช้ Canvas2D เป็นครั้งแรก คุณใช้มาหลายปีแล้ว หรือหลีกเลี่ยงการใช้มาหลายปีแล้ว เราขอบอกให้คุณช่วยเปลี่ยนโฉม Canvas ให้คุณดู ซึ่งเป็น API ที่อยู่ติดกัน ที่อยู่ข้างเคียงมาโดยตลอด

กิตติกรรมประกาศ

รูปภาพหลักของ Sandie Clarke ใน Unsplash