Многократные холсты вызывают перерисовку браузера в `requestAnimationFrame` - PullRequest
0 голосов
/ 28 июня 2019

Я исследую проблемы рисования в одном из моих приложений рендеринга.Я создал простую версию своей проблемы, чтобы понять, почему с двумя холстами перерисовка браузера происходит на каждом кадре.В этом примере используются только два холста и 2D-контексты (для этого примера нет WebGL).

У меня есть HTML-страница, настроенная следующим образом:

+----------------------------+
|                            |
|          CANVAS 1          |
|                            |
|                            |
+----------------------------+
|          | 
| CANVAS 2 | 
|__________|

Код, который я профилирую для этогоПример следующий:

window.onload = init;

const image = document.getElementById('source');
const viewer = { canvas: null, context: null };
const thumbnail = { canvas: null, context: null };

function init() {
    viewer.canvas = document.getElementById('viewer');
    viewer.canvas.width = viewer.canvas.clientWidth;
    viewer.canvas.height = viewer.canvas.clientHeight;
    viewer.context = viewer.canvas.getContext('2d', { alpha: false });

    thumbnail.canvas = document.getElementById('thumbnail');
    thumbnail.canvas.width = thumbnail.canvas.clientWidth;
    thumbnail.canvas.height = thumbnail.canvas.clientHeight;
    thumbnail.context = thumbnail.canvas.getContext('2d', { alpha: false });

    animate();
}

function animate() {
    viewer.context.clearRect(0, 0, viewer.canvas.width, viewer.canvas.height);
    viewer.context.drawImage(image, 0, 0, viewer.canvas.width, viewer.canvas.height);

    thumbnail.context.clearRect(0, 0, thumbnail.canvas.width, thumbnail.canvas.height);
    thumbnail.context.drawImage(image, 0, 0, thumbnail.canvas.width, thumbnail.canvas.height);

    window.requestAnimationFrame(animate);
}
.body {
    position: absolute;
    width: 100%;
    height: 100%;
    margin: 0px;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    display: initial;
    overflow: hidden;
}

.page {
    width: 100%;
    height: 100%;
}

.container {
    position: relative;
    height: 50%;
    width: 100%;
}

.second {
    position: absolute;
    height: 50%;
    width: 80%;
}

canvas {
    width: 100%;
    height: 100%;
}
<div class="page">
    <img
        style="display: none;"
        id="source"
        src="https://mdn.mozillademos.org/files/5397/rhino.jpg"
        width="300"
        height="227"
    >
    <div class="container">
        <canvas id="viewer"></canvas>
    </div>
    <div class="container second">
        <canvas id="thumbnail"></canvas>
    </div>
</div>

Вот что выводит Chrome Profiler:

Profiler: Massive Repaint

Как видите, после каждого requestAnimationFrame происходит перекраска.Здесь она составляет около 0,4 мс, что «хорошо», но в реальном приложении она может составлять около 10 мс, что, очевидно, совсем не нормально, поскольку бюджет кадра составляет 16 мс.

Теперь скажемЯ изменяю ширину .second CSS-класса на:

.second {
  position: absolute;
  height: 50%;
  width: 80%;
}

Страница будет отображаться, как и ожидалось, без чрезмерной перерисовки:

Profiler: No Repaint

В механизме перерисовки браузера есть что-то, о чем я не знаю.Если у кого-то есть подсказка о том, что здесь происходит, было бы здорово поделиться этим со мной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...