← Назад к вопросам

Сколько будет repaint в один кадр?

2.0 Middle🔥 162 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ориентировочное количество репаинтов за кадр

Вопрос «сколько будет repaint в один кадр?» не имеет фиксированного числового ответа, так как количество репаинтов (перерисовок) в течение одного кадра анимации (frame) зависит от множества факторов. В идеальном сценарии современного браузера, стремящегося к высокой производительности и плавности анимаций (60 FPS), целью является НОЛЬ репаинтов на кадр.

Почему ноль — это цель?

Процесс визуального обновления страницы в браузере (рендеринг), часто описываемый конвейером Pixel Pipeline или Rendering Pipeline, состоит из нескольких этапов:

  1. JavaScript → 2. Style Calculation (Recalc Style) → 3. Layout (Reflow) → 4. Paint (Repaint) → 5. Composite.
  • Layout (Перекомпоновка/Reflow): Браузер вычисляет геометрию: размеры и положение каждого элемента. Изменение свойства, влияющего на геометрию (например, width, height, margin, left), запускает этот затратный этап.
  • Paint (Отрисовка/Repaint): Браузер заполняет пиксели: рисует текст, цвета, изображения, тени и т.д. в памяти (в растре). Изменение визуальных свойств, не влияющих на макет (например, color, background-color, visibility, box-shadow), обычно пропускает Layout, но запускает Paint.
    <!-- Пример кода, вызывающего repaint (и, возможно, reflow) -->
    <style>
      .box {
        width: 100px;
        height: 100px;
        background: red;
        transition: background 0.3s;
      }
      .box:hover {
        background: blue; /* Только repaint, layout не нужен */
        /* width: 150px; */ /* Если раскомментировать, добавится и reflow */
      }
    </style>
    <div class="box"></div>
    
  • Composite (Композитинг): Браузер собирает слои (layers) в конечное изображение на экране. Работает с GPU. Изменение свойств, которые обрабатываются композитором (например, transform, opacity), часто позволяет пропустить и Layout, и Paint.

Идеальный кадр происходит, когда изменения затрагивают только этап Composite. Анимация через transform и opacity позволяет браузеру использовать GPU и готовые текстуры слоев, избегая repaint.

Когда repaint происходит в кадре?

  1. Начальный кадр или при первом изменении: При изменении свойства, требующего перерисовки, браузер выполнит repaint для соответствующих областей. Этот repaint происходит внутри данного цикла рендеринга, в рамках отведенных ~16.6 мс (для 60 FPS).
  2. Последующие кадры:
    *   **Худший сценарий**: Если свойство, требующее **repaint** (например, `background-color`), анимируется в цикле `requestAnimationFrame` или через CSS Transitions, то **repaint будет происходить на каждом кадре анимации**. Это большая нагрузка.
```javascript
// ПЛОХО: Вызывает repaint каждый кадр
function animateColor() {
  const element = document.getElementById('box');
  let hue = 0;

  function update() {
    hue = (hue + 1) % 360;
    element.style.backgroundColor = `hsl(${hue}, 100%, 50%)`; // Вызовет repaint
    requestAnimationFrame(update);
  }
  update();
}
```
    *   **Оптимальный сценарий**: Если анимируется только `transform`/`opacity`, то после первого **paint** браузер создает отдельный слой для элемента. В последующих кадрах происходит только **composite**, без нового **repaint**.
```javascript
// ХОРОШО: Скорее всего, вызовет только composite после создания слоя
function animateTransform() {
  const element = document.getElementById('box');
  let pos = 0;

  function update() {
    pos = (pos + 1) % 300;
    element.style.transform = `translateX(${pos}px)`; // Вызовет composite
    requestAnimationFrame(update);
  }
  update();
}
```

Факторы, влияющие на количество и стоимость repaint

  • Размер области перерисовки (Paint Area): Перерисовка всего окна браузера (full repaint) — катастрофа для производительности. Локальный repaint маленького элемента — намного дешевле. Инструменты DevTools (Performance panel, Rendering > Paint flashing) помогают визуализировать области repaint.
  • Сложность стилей элемента: Рисование сложных box-shadow, border-radius, градиентов дороже, чем сплошного цвета.
  • Количество перерисовываемых элементов: Одновременное изменение 100 элементов вызовет больше работы, чем изменение одного.
  • Наличие слоев (Layers): Браузер может поместить элемент на отдельный слой (например, при использовании will-change: transform или 3D-трансформаций). Это изолирует repaint этого элемента, но создание и управление чрезмерным количеством слоев также имеет overhead.

Практический вывод для разработчика

  1. Стремитесь к нулю репаинтов в анимациях. Для этого анимируйте только transform и opacity. Эти свойства оптимизированы для работы композитора.
  2. Избегайте триггеров репаинта в часто выполняемом коде (внутри requestAnimationFrame, scroll, resize итерациях).
  3. Используйте DevTools для профилирования:
    *   Включите `Rendering > Paint flashing`.
    *   Запишите **Performance Trace** и ищите длинные зеленые полосы **Paint** или красные полосы **Layout**.

Итог: В идеально оптимизированной анимации количество repaint за кадр равно 0. В реальности, при изменении свойств, влияющих на внешний вид (но не геометрию), может происходить 1 или более repaint на кадр (по одному для каждой области/слоя), что является узким местом для производительности. Ключевой навык — минимизировать эти случаи и управлять ими.