Canvas เป็นวิธีที่ได้รับความนิยมในการวาดกราฟิกทุกประเภทบนหน้าจอ และเป็นจุดเริ่มต้นสู่โลกของ WebGL ซึ่งสามารถใช้วาดรูปทรง รูปภาพ แสดงภาพเคลื่อนไหว หรือแม้แต่แสดงและประมวลผลเนื้อหาวิดีโอ โดยมักใช้เพื่อสร้างประสบการณ์การใช้งานที่สวยงามในเว็บแอปพลิเคชันและเกมออนไลน์ที่มีสื่อสมบูรณ์
แคนวาสใช้สคริปต์ได้ ซึ่งหมายความว่าเนื้อหาที่วาดบนแคนวาสจะสร้างแบบเป็นโปรแกรมได้ เช่น ใน JavaScript ซึ่งทำให้ Canvas มีความยืดหยุ่นอย่างมาก
ในขณะเดียวกัน การทำงานของสคริปต์เป็นหนึ่งในแหล่งที่มาของปัญหาการตอบสนองของผู้ใช้ที่พบบ่อยที่สุดในเว็บไซต์สมัยใหม่ เนื่องจากตรรกะและการเรนเดอร์ของ Canvas เกิดขึ้นในเธรดเดียวกับการโต้ตอบของผู้ใช้ การประมวลผล (บางครั้งมีปริมาณมาก) ที่เกี่ยวข้องกับภาพเคลื่อนไหวอาจส่งผลเสียต่อประสิทธิภาพจริงและประสิทธิภาพที่รับรู้ของแอป
แต่โชคดีที่ OffscreenCanvas ตอบสนองต่อภัยคุกคามดังกล่าว
ก่อนหน้านี้ ความสามารถในการวาดภาพบนผืนผ้าใบจะเชื่อมโยงกับองค์ประกอบ <canvas>
ซึ่งหมายความว่าจะขึ้นอยู่กับ DOM โดยตรง OffscreenCanvas ตามที่ชื่อบอกไว้จะแยก DOM กับ Canvas API ออกจากกันโดยการย้ายไปไว้นอกหน้าจอ
การแยกนี้ทำให้การแสดงผลของ OffscreenCanvas แยกออกจาก DOM โดยสมบูรณ์ และด้วยเหตุนี้จึงช่วยปรับปรุงความเร็วได้บ้างเมื่อเทียบกับ Canvas ปกติ เนื่องจากไม่มีการซิงค์ระหว่าง 2 รายการ
นอกจากนี้ คุณยังใช้ Web Worker ได้แม้ว่าจะไม่มี DOM ก็ตาม ซึ่งจะทำให้เกิด Use Case ที่น่าสนใจทุกประเภท
ใช้ OffscreenCanvas ใน Worker
Workers คือเธรดเวอร์ชันเว็บ ซึ่งช่วยให้คุณทำงานในเบื้องหลังได้
การย้ายสคริปต์บางส่วนไปยังเวิร์กเกอร์จะช่วยให้แอปมีเวลาเหลือมากขึ้นในการดําเนินการที่สำคัญต่อผู้ใช้ในเธรดหลัก หากไม่มี OffscreenCanvas คุณจะไม่สามารถใช้งาน Canvas API ใน Worker ได้ เนื่องจากไม่มี DOM
OffscreenCanvas ไม่ได้ขึ้นอยู่กับ DOM จึงใช้งานได้ ตัวอย่างต่อไปนี้ใช้ OffscreenCanvas เพื่อคํานวณสีไล่ระดับในเวิร์กเกอร์
// file: worker.js
function getGradientColor(percent) {
const canvas = new OffscreenCanvas(100, 1);
const ctx = canvas.getContext('2d');
const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'blue');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, ctx.canvas.width, 1);
const imgd = ctx.getImageData(0, 0, ctx.canvas.width, 1);
const colors = imgd.data.slice(percent * 4, percent * 4 + 4);
return `rgba(${colors[0]}, ${colors[1]}, ${colors[2]}, ${colors[3]})`;
}
getGradientColor(40); // rgba(152, 0, 104, 255 )
เลิกบล็อกชุดข้อความหลัก
การย้ายการคํานวณที่หนักไปยังผู้ปฏิบัติงานจะช่วยให้คุณมีทรัพยากรจำนวนมากในชุดข้อความหลัก ใช้เมธอด transferControlToOffscreen เพื่อมิเรอร์ภาพพิมพ์แคนวาสปกติไปยังอินสแตนซ์ OffscreenCanvas ระบบจะแสดงผลการดำเนินการที่ใช้กับ OffscreenCanvas บน Canvas ต้นทางโดยอัตโนมัติ
const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({canvas: offscreen}, [offscreen]);
ในตัวอย่างต่อไปนี้ การคํานวณที่หนักหน่วงเกิดขึ้นเมื่อธีมสีมีการเปลี่ยนแปลง ซึ่งอาจใช้เวลา 2-3 มิลลิวินาทีแม้ในเดสก์ท็อปที่เร็ว คุณเลือกที่จะแสดงภาพเคลื่อนไหวในเธรดหลักหรือในเวิร์กเกอร์ก็ได้ ในกรณีที่เป็นเธรดหลัก คุณจะโต้ตอบกับปุ่มไม่ได้ขณะที่งานที่มีทรัพยากรมากกำลังทำงานอยู่ เนื่องจากเธรดถูกบล็อก ในกรณีของโหนดงาน จะไม่มีผลต่อความตอบสนองของ UI
ในทางกลับกัน เทรดหลักที่ทำงานอยู่จะไม่ส่งผลต่อภาพเคลื่อนไหวที่ทำงานอยู่บนเวิร์กเกอร์ คุณสามารถใช้ฟีเจอร์นี้เพื่อหลีกเลี่ยงภาพกระตุกและรับประกันภาพเคลื่อนไหวที่ราบรื่นแม้จะมีการเข้าชมเธรดหลักก็ตาม ดังที่แสดงในตัวอย่างต่อไปนี้
ในกรณีที่ใช้ Canvas ปกติ ภาพเคลื่อนไหวจะหยุดเมื่อเธรดหลักทำงานหนักเกินจริง ในขณะที่ OffscreenCanvas ที่อิงตามเวิร์กเกอร์จะเล่นได้อย่างราบรื่น
ใช้กับไลบรารียอดนิยม
เนื่องจาก OffscreenCanvas API โดยทั่วไปเข้ากันได้กับองค์ประกอบ Canvas ปกติ คุณจึงใช้ API นี้เป็นการปรับปรุงแบบเป็นขั้นเป็นตอน รวมถึงใช้กับไลบรารีกราฟิกชั้นนําบางรายการในตลาดได้
เช่น คุณสามารถตรวจหาองค์ประกอบและนำไปใช้กับ Three.js ได้ (หากมี) โดยระบุตัวเลือก Canvas ในเครื่องมือสร้างโปรแกรมแสดงผล ดังนี้
const canvasEl = document.querySelector('canvas');
const canvas =
'OffscreenCanvas' in window
? canvasEl.transferControlToOffscreen()
: canvasEl;
canvas.style = {width: 0, height: 0};
const renderer = new THREE.WebGLRenderer({canvas: canvas});
สิ่งที่ควรทราบคือ Three.js คาดหวังว่า Canvas จะมีพร็อพเพอร์ตี้ style.width
และ style.height
OffscreenCanvas ไม่ได้มีค่าเหล่านี้เนื่องจากไม่ได้เชื่อมโยงกับ DOM โดยสมบูรณ์ คุณจึงต้องระบุค่าด้วยตนเอง ไม่ว่าจะโดยการวางเมาส์วางไว้หรือระบุตรรกะที่เชื่อมโยงค่าเหล่านี้กับมิติข้อมูลแคนวาสเดิม
ตัวอย่างต่อไปนี้แสดงวิธีเรียกใช้ภาพเคลื่อนไหว Three.js พื้นฐานในเวิร์กเกอร์
โปรดทราบว่า API บางอย่างที่เกี่ยวข้องกับ DOM อาจไม่พร้อมใช้งานในเวิร์กเกอร์ ดังนั้นหากต้องการใช้ฟีเจอร์ขั้นสูงของ Three.js เช่น พื้นผิว คุณอาจต้องใช้วิธีแก้ปัญหาเพิ่มเติม หากต้องการทราบแนวคิดเกี่ยวกับวิธีเริ่มทดสอบฟีเจอร์เหล่านี้ โปรดดูวิดีโอจาก Google I/O ปี 2017
หากคุณใช้ความสามารถด้านกราฟิกของ Canvas อย่างมาก OffscreenCanvas อาจส่งผลเชิงบวกต่อประสิทธิภาพของแอป การทำให้บริบทการแสดงผลแคนวาสพร้อมใช้งานสำหรับเวิร์กเกอร์จะเพิ่มการทำงานแบบขนานในเว็บแอปพลิเคชันและใช้ประโยชน์จากระบบแบบหลายแกนได้ดียิ่งขึ้น