Оптимизация простой сцены PixiJS

Я новичок в Pixi, WebGL, Canvas ... и на самом деле я делаю не игру, а веб-приложение на React

Что хочу построить:

  • Нарисуйте изображение (сканирование документа A4, обычно jpeg / png от 100k до 1m)
  • Поверх каждого слова изображения нарисуйте интерактивный прямоугольник, который можно навести / щелкнуть
  • Благодаря глубокому обучению / OCR у меня уже есть размер изображения и взаимное расположение слов документа.
  • В документах может быть от 0 до 3000 слов.
  • Возможность увеличения

Оптимизация простой сцены PixiJS

Сначала я попробовал использовать обычный CSS, но ясно обнаружил, что использование абсолютной позиции неэффективно для размещения тысяч прямоугольников в документе: например, производительность при прокрутке была невысокой.

Я попытался использовать PixiJS, чтобы нарисовать прямоугольники поверх изображения. Результат лучше, но я все еще вижу некоторые проблемы с производительностью на моем старом компьютере, особенно когда изображение увеличено (это влияет на прокрутку, поэтому я думаю, это не совсем связано с кодом JS)


Вот результат: https://dhatim-poc-mlhafeauav.now.sh/

Решение, которое я использовал для вышеуказанного документа:

  • Тег HTML img
  • Прозрачный холст поверх изображения, на котором я рисую прямоугольники (Graphics, drawRect)

Может кто-нибудь сказать мне, как оптимизировать это для старых компьютеров? Как я могу правильно проверить производительность этого решения? Есть ли простой способ смоделировать старый компьютер на моем dev env? особенно в отношении GPU вместо троттлинга CPU?


Я попытался следовать некоторым рекомендациям, найденным здесь: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas

  • Я использую фоновое изображение вместо того, чтобы рисовать изображение на холсте (не уверен, что это окажет большое влияние, потому что нет «игрового цикла»)
  • Я использую Math.floor для позиции слов (опция PixiJS roundPixels)
  • Я также пробовал с небольшим холстом и масштабным преобразованием: https://build-ybbdwoumva.now.sh/

Есть ли другие рекомендации, которые вы могли бы дать, чтобы добиться лучших результатов?

Особенно:

  • я должен использовать Sprite или Graphics для прямоугольников?
  • я должен использовать холст или WebGL?
  • как я могу измерить мою оптимизацию производительности? В настоящее время я чувствую себя совершенно слепым и даже не уверен, что то, что я делаю, дает лучший результат без конкретных цифр.

Спасибо

Что, если вы поместите все элементы прямоугольника в родительский элемент и установите масштаб style.transform для этого элемента. Затем вам нужно обновить только один элемент для увеличения.

gman 09.08.2018 13:20

Да, на самом деле я мог сделать это и обработать масштабирование с помощью только операции масштабирования, не требуя перерисовки на холсте. На самом деле я, вероятно, сделаю это, но в настоящее время я уже сталкиваюсь с некоторой медлительностью, просто прокручивая на старом компьютере, даже не перерисовывая на холсте. Я предполагаю, что это как-то связано с размером изображения и плохой графической картой на компьютере, и мне интересно, могу ли я что-то с этим поделать. Кроме того, масштабирование или изменение размеров браузера не являются наиболее распространенными операциями, поэтому, если это занимает 300 мс, это не имеет большого значения для моего варианта использования.

Sebastien Lorber 09.08.2018 13:26
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
TL;DR: Angular Signals может облегчить отслеживание всех выражений в представлении (Component или EmbeddedView) и планирование пользовательских...
Sniper-CSS, избегайте неиспользуемых стилей
Sniper-CSS, избегайте неиспользуемых стилей
Это краткое руководство, в котором я хочу поделиться тем, как я перешел от 212 кБ CSS к 32,1 кБ (сокращение кода на 84,91%), по-прежнему используя...
0
2
752
1

Ответы 1

Что, если вы поместите все элементы прямоугольника в родительский элемент и установите для этого элемента масштаб style.transform. Затем вам нужно обновить только один элемент для увеличения.

const parent = document.querySelector(".areas>div");
const pair = document.querySelector(".viewer>div");

const imgWidth = 600;
const imgHeight = 849;
const numAreas = 1000;
for (let i = 0; i < numAreas; ++i) {
  const x = rand(imgWidth - 10);
  const y = rand(imgHeight - 10);
  const w = rand(5, imgWidth - x);
  const h = rand(5, imgHeight - y);
  
  const area = document.createElement("div");
  area.className = "area";
  area.style.left = px(x);
  area.style.top = px(y);
  area.style.width = px(w);
  area.style.height = px(h);
  parent.appendChild(area);
}

document.querySelector("#zoom").addEventListener('input', (e) => {
  const s = e.target.value / 100;
  const transform = `scale(${s},${s})`;
  pair.style.transform = transform;
});

function rand(min, max) {
  if (max === undefined) {
    max = min;
    min = 0;
  }
  return Math.random() * (max - min) + min | 0;
}

function px(v) {
  return `${v}px`;
}
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
.viewer {
  position: relative;  /* so children are relative to this */
}
.area { 
  border: 1px solid red;
}
.area:hover {
  border: 1px solid yellow;
}
.areas {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 2;
  /* to match image */
  width: 600px;
  height 849px;
}
.areas>div {
  position: relative;  /* so children are relative to this */
  width: 100%;
  height: 100%;
}
.areas>div>div {
  position: absolute;
}
.ui {
  position: absolute;
  left: 1em;
  top: 1em;
  background: rgba(0,0,0,.8);
  color: white;
  padding: .5em;
  z-index: 3;
}
.ui>input {
  width: 100%;
}
<div class = "viewer">
  <div>
    <img src = "https://i.imgur.com/TSiyiJv.jpg">
    <div class = "areas">
      <div>
      </div>
    </div>
  </div>
</div>
<div class = "ui">
 <label for = "zoom">zoom</label>
 <input type = "range" min = "1" max = "500" value = "100" id = "zoom">
</div>

Я не стал его убирать, устанавливать полосы прокрутки и т. д., Но вроде работает

Привет, спасибо за ваше предложение, но я уже пытался визуализировать 1000 элементов с абсолютной позицией поверх изображения, вообще без функции масштабирования, и это было недостаточно производительно при прокрутке на компьютерах низкого уровня. Вот почему я сейчас использую холст. Проблема для меня на самом деле не во времени, необходимом для рендеринга, а в том, сколько нарисованное потребляет ресурсов на старых компьютерах (т.е. плавная прокрутка).

Sebastien Lorber 09.08.2018 16:05

Кроме того, если вы проверите эту версию, вы увидите, что мой холст имеет фиксированный размер, и я использую на нем масштабное преобразование: build-ybbdwoumva.now.sh

Sebastien Lorber 09.08.2018 16:06

Другие вопросы по теме