【问题标题】:Performance issues with kineticjskineticjs 的性能问题
【发布时间】:2013-09-10 00:24:19
【问题描述】:

随着画布上形状数量的增加,我在使用 kineticjs 时遇到了一些严重的性能问题。我有两个函数,一个初始化路径、一个文本并将它们呈现在舞台上。第二个函数每 5 秒调用一次,它会更新之前绘制的路径和文本的任何更改。 这是我正在尝试的示例 sn-p,

  /**
  * Function that inits the shapes
  */
  init = function(params) {
  //Create the path object
  var path = new Kinetic.Path({
    data : params.geom,
    fill : params.fill,
    stroke : params.stroke.fill,
    strokeEnabled : false,
    scale : 1
  });
  path.setId(params.id + '.path');
  var simpleText = new Kinetic.Text({
    x : params.x,
    y : params.y + (params.height /2),
    text : params.displayText,
    fontSize : 12,
    fontFamily : params.family,
    fontStyle : params.style,
    fill : params.fill
  });
  simpleText.setId(params.id + '.text');

  var layer = new Kinetic.Layer();
  layer.setId(params.id);
  layer.add(path);
  layer.add(simpleText);
  stage.add(layer);
}

/**
* Update every 5 seconds based on new data
*/
update = function(params) {
  var layer = null;
  if (Kinetic.Global.ids[params.id] != undefined) {
    layer = Kinetic.Global.ids[params.id];
    //Set text
    var textItem = Kinetic.Global.ids[params.id + '.text'];
    textItem.setText(params.displayText);
    //center the text
    textItem.setAttr('x', params.x + (params.width / 2) - (textItem.textWidth / 2));
    textItem.setAttr('y', params.y + (params.height / 2) -            textItem.getAttr('fontSize'));
    // set center style
    textItem.setAlign('center');
    //Set path color
    var pathItem = Kinetic.Global.ids[params.id + '.path'];
    pathItem.setFill(params.fill);
    pathItem.setOpacity(params.alpha);

    layer.clear();
    layer.draw();
  }
}

随着要绘制的形状数量的增加,此代码将变得缓慢并消耗大量内存。 上面的代码中可能有很多地方需要改进,我正在寻找那些指针。具体来说,我不相信 Id 查找和更新是否是更新现有形状的最佳方式。

【问题讨论】:

    标签: kineticjs


    【解决方案1】:

    您可以使用layer.get('#someID') 函数,而不是通过Kinetic.Global.ids 对象查找对象。不确定这是否会对性能有很大帮助,但这是一个开始。

    另外,我认为您不需要每次更新时都使用layer.clear() 图层,对吗?我认为layer.draw() 应该足以更新形状。

    一个建议:也许您可能只需要每 5 秒使用一次 drawScene() 而不是 draw() 这可能会有所帮助,因为您不需要重绘 命中层 em> 每次。 Kinetic draw 函数的区别见这里:What is the difference between KineticJS draw methods?

    无论如何,每 5 秒在图层上使用draw() 方法会非常昂贵,尤其是当图层中开始有很多形状时。 p>

    另一个重要的问题是:你的对象总是每 5 秒改变一次吗?我的意思是,有时您可能不需要绘制图层,因为没有发生更新。如果可以检查对象是否已更新,则可以决定是否需要调用更新函数以及是否需要重绘图层。

    我的最后一个建议是建立在最后一点的基础上,也许你不需要每次都重绘图层,因此重绘图层内的所有对象,其中可能不是图层中的所有对象都已更新(并且需要重绘)。 可能只有部分对象已更新。在这种情况下,如果您使用Kinetic.Group 将每个文本/路径组合在一起,您可以使用group.draw() 而不是layer.draw()。现在,如果您可以找到每 5 秒更新一次数据的组,您只需绘制 Kinetic.Group而不是每 5 秒绘制整个图层

    顺便说一句,你也可以像这样使用.get()函数:

    var layers = stage.get('Layer'); // Returns an array of all Kinetic.Layers inside stage
    var groups = layers[0].get('Group'); // Returns an array of all Kinetic.Groups inside the first layer (in the layers array)
    

    有关 get 方法的更多信息,请参见此处:http://kineticjs.com/docs/Kinetic.Container.html#get

    【讨论】:

    • 这些很重要,我已经实施了一些谢谢!然而,显着提高性能的更改是只为我的每个图形项目(包括路径和文本)使用单个图层而不是图层。我的要求是支持大约 1000 个图形项目,每个图形项目都有一个路径和一个文本,现在这似乎工作正常。但是,如果需求发生变化以支持更多,我相信我可能需要不止一个层。
    • 是的,当然!您不希望每个项目都有一个层(不确定在上面的代码中是否很明显),因为这将对性能造成巨大影响。试想一下,每一层向 DOM 添加 2 个画布,一个用于渲染节点,一个用作命中画布。相反,如果您需要将节点组合在一起,请使用 Kinetic.Group 更多信息请参阅此链接:stackoverflow.com/questions/17632068/…
    • 谢谢,组现在就位,性能要好得多。
    猜你喜欢
    • 2023-03-30
    • 2012-08-17
    • 2014-01-28
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 2012-08-29
    • 2017-04-13
    相关资源
    最近更新 更多