【问题标题】:Optimizing simple PixiJS stage优化简单 PixiJS 阶段
【发布时间】:2019-01-16 19:12:08
【问题描述】:

我对 Pixi、WebGL、Canvas 完全陌生......实际上我不是在制作游戏,而是在制作 React webapp

我想构建什么:

  • 画图(A4文件扫描,一般jpeg/png从100k到1m)
  • 在图片的每个单词上方,绘制一个可以悬停/单击的交互式矩形
  • 感谢深度学习/OCR,我已经有了图像的大小和文档单词的相对位置
  • 文档可以包含 0 到 3000 个单词
  • 能够缩放

我首先尝试使用常规 CSS,但清楚地发现使用绝对位置在文档上定位数千个矩形时性能不佳:例如,在滚动时性能不佳。

我尝试使用 PixiJS 在图像顶部绘制矩形。结果更好,但我仍然在我的旧电脑上看到一些性能问题,特别是当图像缩放时(它会影响滚动,所以我猜它与 JS 代码并没有真正的关系)


结果如下:https://dhatim-poc-mlhafeauav.now.sh/

我用于上述文档的解决方案:

  • html img 标签
  • 位于图像顶部的透明画布,我在其上绘制矩形(图形、drawRect)

谁能告诉我如何针对旧计算机优化此功能? 如何正确审核此解决方案的性能? 有没有一种简单的方法可以在我的开发环境中模拟旧计算机?特别是关于 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 比例尺会怎样。然后你只需要更新一个元素来缩放。
  • 是的,实际上我可以做到这一点,只用缩放操作来处理缩放,而不需要在画布上重绘。实际上我可能会这样做,但目前我已经在旧电脑上滚动时遇到了一些缓慢,甚至没有在画布上重绘。我想这与图像大小和计算机上糟糕的图形卡有关,我想知道我是否可以对此做点什么。此外,缩放或浏览器调整大小不是最常见的操作,所以如果需要 300 毫秒,这对我的用例来说没什么大不了

标签: performance canvas webgl pixi.js


【解决方案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 个绝对位置的元素,根本没有缩放功能,并且在低端计算机上滚动时性能不够.这就是我现在使用画布的原因。对我来说,问题不在于渲染所需的时间,而是绘制的内容在旧计算机上消耗了多少资源(即保持滚动流畅)
  • 另外,如果你检查这个版本,你可以看到我的画布有一个固定的大小,我在上面使用了缩放变换:build-ybbdwoumva.now.sh
猜你喜欢
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
相关资源
最近更新 更多