OutscreenCanvas – האצת פעולות בד קנבס בעזרת worker באינטרנט

Tim Dresser

לוח הציור הוא דרך פופולרית של ציור כל סוגי הגרפיקה על המסך ונקודת כניסה לעולם של WebGL. אפשר להשתמש בו כדי לשרטט צורות, תמונות, להריץ אנימציות ואפילו להציג ולעבד תוכן וידאו. לרוב משמש ליצירת חוויות משתמש מרהיבות ביישומי אינטרנט עשירים במדיה משחקים מקוונים.

הוא ניתן לסקריפט, כלומר ניתן ליצור את התוכן שמשורטט על קנבס באופן פרוגרמטי, למשל, ב-JavaScript. כך הקנבס נותן גמישות רבה.

עם זאת, באתרים מודרניים, ביצוע סקריפטים הוא אחד בעיות שקשורות למקורות לתגובת המשתמשים. מכיוון שהלוגיקה של לוח הציור והרינדור מתרחשים באותו שרשור כמו האינטראקציה של המשתמש, החישובים (שלפעמים הכבדים) הכרוכים באנימציות יכולים לפגוע במציאות ואת תפיסת הביצועים.

למרבה המזל, OffscreenCanvas הוא תגובה לאיום הזה.

תמיכה בדפדפן

  • 69
  • 79
  • 105
  • 16.4

מקור

בעבר, יכולות השרטוט של אזור העריכה על קנבס היו מקושרות לרכיב <canvas>, ולכן זה היה תלוי ישירות ב-DOM. OffscreenCanvas, כפי שמרמז השם, מפריד בין ה-DOM ל-Canvas API על ידי העברתו אל מחוץ למסך.

בזכות הניתוק הזה, העיבוד של OffscreenCanvas נותק לגמרי מה-DOM ולכן מציע שיפורי מהירות מסוימים באזור העריכה הרגיל מכיוון שאין סנכרון בין שני הסוגים.

יותר מכך, ניתן להשתמש בו רק במסגרת Web Worker, DOM זמין. כך אפשר להשתמש בכל סוגי התרחישים המעניינים.

שימוש ב-OffscreenCanvas בעובד

עובדים הן גרסת השרשורים באינטרנט – הם מאפשרים להריץ משימות ברקע.

העברה של חלק מהסקריפטים לעובד נותנת לאפליקציה יותר מקום לבצע פעולות קריטיות למשתמשים ב-thread הראשי. בלי OffscreenCanvas, לא הייתה דרך להשתמש ב-Canvas API ב-Workvas, לא היה 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 )

ביטול החסימה של השרשור הראשי

העברת חישובים עמוסים לעובד מאפשרת לך לפנות מקום משאבים משמעותיים ב-thread הראשי. משתמשים ב-transferControlToOffscreen כדי לשקף את הקנבס הרגיל במכונה של OffscreenCanvas. הפעולות שחלות על אזור העריכה מחוץ למסך התמונה יתבצע באופן אוטומטי באזור העריכה של המקור.

const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({canvas: offscreen}, [offscreen]);

בדוגמה הבאה, החישוב הכבד מתרחש כאשר ערכת הצבעים משתנה - היא אמורה נדרשות כמה אלפיות שנייה גם במחשבים מהירים. אפשר להריץ אנימציות בשרשור הראשי או עובד/ת. אם מדובר ב-thread הראשי, אי אפשר ללחוץ על הלחצן בזמן שהעומס כבר פועלת — השרשור חסום. במקרה של העובד, לא תהיה השפעה על רספונסיביות של ממשק המשתמש.

הדגמה

זה עובד גם בכיוון השני: ה-thread הראשי העמוס לא משפיע על האנימציה שפועלת בו עובד. ניתן להשתמש בתכונה הזו כדי למנוע בעיות חזותיות ולהבטיח שהאנימציה תהיה חלקה למרות התנועה בשרשור הראשי, כפי שמוצג בהדגמה הבאה.

הדגמה

אם מדובר על קנבס רגיל, האנימציה מפסיקה כשה-thread הראשי מקבל עומס יתר באופן מלאכותי, בזמן שהמשחק OffscreenCanvas שפועל על בסיס עובד יכול לפעול בצורה חלקה.

מכיוון ש-OffscreenCanvas API תואם בדרך כלל לרכיב Canvas הרגיל, אתם יכולים להשתמש בה כשיפור הדרגתי, עם כמה מהספריות הגרפיות המובילות בשוק.

לדוגמה, תוכלו לזהות תכונה זו, ואם הדבר אפשרי, להשתמש בו עם Three.js על-ידי ציון אפשרות הקנבס ב-constructor של כלי הרינדור:

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 מצפה שהקנבס יכלול נכס style.width ו-style.height. ל-OffscreenCanvas, למרות הניתוק המלא מ-DOM, אין לו, לכן עליכם לספק אותו בעצמכם, על ידי חריגת ההיררכיה או באמצעות לוגיקה שקושרת את הערכים האלה למקור מידות הקנבס.

ההוראות הבאות מראות איך להריץ אנימציה בסיסית של Three.js ב-Worker:

הדגמה

חשוב לזכור שחלק מממשקי ה-API שקשורים ל-DOM לא זמינים מראש ב-Worker, כך שאם אם אתם רוצים להשתמש בתכונות מתקדמות יותר של Three.js, כמו טקסטורות, ייתכן שתצטרכו עוד דרכים לעקוף את הבעיה. כדי לקבל רעיונות להתחלת הניסויים האלה, אפשר לעיין סרטון מ-Google I/O 2017.

אם אתם משקיעים הרבה ביכולות הגרפיות של לוח הציור, אפשר להשתמש ב-OffscreenCanvas להשפיע על ביצועי האפליקציה. הגדלת ההקשרים של עיבוד קנבס עבור העובדים מקבילה באפליקציות אינטרנט ומנצלת טוב יותר מערכות מרובות ליבות.

מקורות מידע נוספים