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 อาจส่งผลเชิงบวกต่อประสิทธิภาพของแอป การทำให้บริบทการแสดงผลแคนวาสพร้อมใช้งานสำหรับเวิร์กเกอร์จะเพิ่มการทำงานแบบขนานในเว็บแอปพลิเคชันและใช้ประโยชน์จากระบบแบบหลายแกนได้ดียิ่งขึ้น