Теперь вам не нужно рисовать изображения в основном потоке благодаря Offscreen Canvas!
CanvasЭто очень популярное представление, а также точка входа в WebGL. Он может рисовать графику, картинки, отображать анимацию и даже обрабатывать видеоконтент. Он часто используется для создания классных пользовательских интерфейсов в мультимедийных веб-приложениях или для создания онлайн-игр.
Он очень гибкий, а это значит, что содержимое, нарисованное на холсте, можно запрограммировать. Например 🌰, JavaScript предоставляет ряд API для Canvas. Это дает Canvas большую гибкость.
Но в то же время на некоторых современных веб-сайтах синтаксический анализ и запуск сценариев является одной из самых больших проблем для обеспечения плавной обратной связи с пользователем. Поскольку вычисление и рендеринг Canvas, а также реакция пользователя на операцию происходят в одном потоке, операция вычисления в анимации (иногда занимающая много времени) приведет к зависанию приложения и ухудшению взаимодействия с пользователем.
К счастью,OffscreenCanvasВы можете решить эту проблему на экране Hanvas!
До сих пор функции холста и рисования<canvas>
Теги связаны вместе, что означает, что Canvas API и DOM связаны. OffscreenCanvas, как следует из названия, разделяет DOM и Canvas API, перемещая Canvas за пределы экрана.
Из-за этого разъединения рендеринг OffscreenCanvas полностью отделен от DOM, и он немного быстрее, чем обычный Canvas, просто потому, что между ними (Canvas и DOM) нет синхронизации. Но что более важно, после их разделения Canvas можно будет использовать в Web Worker, даже если в Web Worker нет DOM. Это открывает больше возможностей для Canvas.
Использование OffscreenCanvas в Worker
Workers— это веб-версия потоков — она позволяет запускать ваш код за кулисами. Размещение части вашего кода в Worker может дать вашему основному потоку больше времени простоя, что улучшит ваш пользовательский опыт. Точно так же, как у него нет DOM, до сих пор в Worker не было Canvas API.
OffscreenCanvas не зависит от DOM, поэтому Canvas API можно заменить каким-либо методом в Worker. Вот как я использую OffscreenCanvas в Worker для расчета цвета градиента 🌰:
// 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[]);
}
getGradientColor(40); // rgba(152, 0, 104, 255 )
Не блокируйте основную нить
Интересно освободить ресурсы на главной ните, когда мы перемещаем много вычислений для работника. Мы можем использовать метод TransferControLTooffscreen для отображения обычного холста в экземпляр Offscreencanvas. Все последующие операции, применяемые к OffScreencanvas, будут автоматически представлены на холсте источника.
const offscreen = document.querySelector('canvas').transferControlToOffscreen();
const worker = new Worker('myworkerurl.js');
worker.postMessage({ canvas: offscreen }, [offscreen]);
OffscreenCanvas [передается](developer.Mozilla.org/en-US/docs/…). Помимо указания его как одного из полей в переданном сообщении, его также необходимо передать вторым параметром в postMessage (метод, который передает сообщение в Worker), чтобы его можно было использовать в контексте Worker нить .
В 🌰 ниже при изменении цветовой темы происходит «сложный расчет», и этот расчет занимает несколько миллисекунд даже на высокопроизводительном рабочем столе. И вы можете запустить эту анимацию в основном потоке или в рабочем потоке. В основном потоке вы не сможете взаимодействовать с кнопкой, пока запускаются сложные вычисления — поток заблокирован. Под Worker не влияет на реакцию UI.
Это также другой способ интерпретации: загруженный основной поток также не влияет на анимацию, выполняемую на рабочем потоке. Таким образом, даже если основной поток очень занят, вы можете использовать эту функцию, чтобы избежать пропуска кадров и обеспечить плавную анимацию:
В приведенном выше примере показан генеральный холст, когда основной поток занят, добавляя анимационную задачу, заблокирована, и на основе Offscreencanvas работника работают очень свободно.
Использование с популярными библиотеками
Поскольку API OffscreenCanvas в целом совместим с API обычного элемента Canvas, вы можете легко использовать его поэтапно или использовать некоторые из лучших графических библиотек/фреймворков в сообществе.
Например 🌰, вы можете выполнить обнаружение на нем функции, если она доступна, указав элемент конфигурации холста в конструкторе рендеринга, а затем реализовать функцию, используемую с Three.js:
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, либо написав собственную логику, связывающую эти значения с начальными измерениями Canvas.
Вот демонстрация базовой анимации Three.js:
Но помните, что есть некоторые, связанные с API DOM. Некоторые идеи в этом отношении начали пытаться проверитьВидео с Google I/O 2017.
Метод commit(), показанный в примерах в этом видео, не рекомендуется. Вместо этого используйте worker.requestAnimationFrame.
В заключение
Если вы часто рисуете изображения, OffscreenCanvas может эффективно повысить производительность вашего приложения. Это позволяет Worker обрабатывать рендеринг холста, позволяя вашему приложению лучше использовать преимущества многоядерной системы.
OffscreenCanvas можно использовать в Chrome 69 без включения флага (экспериментальная функция). Он также реализуется Firefox. Поскольку его API очень похож на обычный элемент холста, вы можете легко добавить его и использовать шаг за шагом, не нарушая логику работы вашего существующего приложения или библиотеки. OffscreenCanvas имеет преимущества в производительности в любой ситуации, связанной с графическими вычислениями и производительностью анимации, и не имеет тесной связи с DOM (то есть не сильно зависит от DOM API).