В попытках оптимизировать 2D анимацию созданную в canvas, был найден один интересный вариант.
Предварительная визуализация — prerender.
"А что если записать все кадры заранее и показать их после окончания анимации?" — подумали мы с товарищем и вот что получилось на следующий день.
Live demo
Code v1.0
Сама страница есть на Github.
Логика очень проста и реализуется в 2 шага:
Шаг 1 — Сохраняем каждый кадр нашей анимации в массив изображений
function renderLoop() {
draw();
// create prerender images
canvasPrerender.toBlob(blob => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function() {
const image = document.createElement("img");
image.src = reader.result;
prerenderArr.push(image);
};
});
if (prerenderIsCompleted) {
requestAnimationFrame(renderLoop);
} else {
requestAnimationFrame(drawPreImg);
}
}
Шаг 2 — После окончания — рисуем анимацию из уже готовых изображений
function drawPreImg() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(prerenderArr[i], 0, 0);
requestAnimationFrame(drawPreImg);
}
Analytic
Конкретные значения индивидуальны и зависят от мощности машины. Я тестирую на macbook 13 2019 года.
Давайте посмотрим на код и затраты ресурсов в том числе и временных.
FPS
Fps "до" равен частоте кадров если бы мы запустили анимацию сразу без предварительной отрисовки.
Fps "до" запуска анимации (prerender): 14-22
Fps "после" (сама анимация): 58-60
На скриншоте выше используется более сложное изображение, чем в live demo.
Время
Prerender — 9 секунд
Сама анимация — 3 секунды
Общее — 12 секунд (так же на live demo)
CPU / Performance
Как видно из скриншота ниже — наш процессор страдает только на этапе prerender'а. Нарисовать уже готовые изображения не составляет труда.
Память
Для небольшой анимации как у нас всё это дело занимает:
~ 432 / 2 = 200 кадров
~ 25 мб
Conclusion
Если у вас есть возможность подождать, прежде чем показать анимацию пользователю и она не будет съедать Гигабайты памяти — попробуйте сделать что то подобное.
P.S.
Если у вас есть идеи по повышению производительности данного подхода — пишите :)