使用大帆布更快地滚动/平移?

时间:2016-01-20 01:42:42

标签: javascript html5 canvas

我有一个基本上是大画布的页面,其中有许多小图标与线条连接,用户需要能够平移/缩放。我已经把一切都搞定了,但它非常不稳定。似乎重新绘制是问题(如果我删除图标它变得非常流畅),但如果我运行Chrome的分析器,我的所有功能都没有占用任何重要的时间。

有没有更好的平移方法,而不必重新绘制所有内容?例如,在WinAPI中,有一个滚动窗口内容的函数,只使刚刚滚动到视图中的瘦区域无效。有没有办法在Javascript / canvas中做类似的事情,因为我真正需要的只是移动整个窗口?

我已经尝试制作一个巨大的画布,上面已经预先绘制了所有内容,然后使用scrollLeft / scrollTop移动,但这需要方式太多内存(我还应该期待什么? 4000x4000图像)并且变焦非常慢。

如果有人感兴趣的话,这里是页面,代码很可读,我希望:

http://poe.rivsoft.net/

1 个答案:

答案 0 :(得分:2)

你必须忍受一些较慢的部分。考虑创建脏区域。这些是在平移时需要重绘的区域。保持后缓冲区与画布大小相同。当从后缓冲区向其自身平移复制时,该区域仍然可见并将新可见区域标记为脏。然后每个帧只将脏区域重新渲染到后缓冲区。对于缩放,您可以缩放后缓冲区并在用户暂停或递增时重新渲染,这将在放大时创建像素化视图(如谷歌地图),或在缩小时创建边框上的脏区域,直到您更新它。

您还可以限制每帧重绘的脏区数量,以保持恒定的帧速率。它不会看起来不错,但它会改善平移和缩放。在我的机器上运行良好(BTW工作很好)所以你可能只想在无法处理负载的机器上实现优化。

同时查看函数DrawNode还有很多优化空间,因为你有很多冗余代码(特别是一旦所有资源都加载了)

这只是一个建议,因为我不知道节点是否是唯一的,或者x,y坐标是否改变,但也可以适应。你有很多应该避免的搜索和检查。使用字符串而不是数字或布尔来检查状态和类型也很慢。

  function DrawNode(ctx, node, x, y, active) {
      // Has this node got quick render information 
      if (node.qNode) {  
          // if so render the quick version
          var qn = node.qNode; // creating the var qn and then qn.? is quicker than access node.qNode.? 
          ctx.drawImage(qn.image, qn.coords.x, qn.coords.y, qn.coords.w, qn.coords.h, qn.x, qn.y, qn.size, qn.size);
          return;
      }
      var type = NodeTypes[node.type];
      var frameType = "frame" + (active ? "Active" : "Inactive");  // active should be a boolean
      if (type && type.size && node.type !== "jewel") { // should be !node.isJewel with isJewwl a boolean
          var spriteType = node.type;
          if (node.type !== "mastery") // Should be boolean
              spriteType += (active ? "Active" : "Inactive");
          var sprites = SkillTree.skillSprites[spriteType][3];
          var image = GetImage("Assets/" + sprites.filename);
          var coords = sprites.coords[node.icon];
          if (image && image.loaded && coords) {
              ctx.drawImage(image, coords.x, coords.y, coords.w, coords.h,
                  x - type.size * 0.5, y - type.size * 0.5, type.size, type.size);

              // add the information to quickly render the node next time. 
              // You may want to add sub objects for Mastery Active,inactive
              node.qNode = {
                  image : image,
                  coords : coords,
                  x : x - type.size * 0.5,
                  y : y - type - sise * 0.5,
                  size : type.size
              }

          } else if (!image || !image.loaded) {
              return false;
          }
      }
      // same deal for the other type.
  }

优化时,从最慢点开始,尽可能提高代码效率,然后逐步解决问题。这是一个编写良好的代码,但它没有关注速度,所以我想说代码有更多的改进空间。