2

I'm currently trying to speed my web app for mobile devices a little bit up, but now I'm stuck at the most important part - caching. How is it possible to cache a entire layer right before the user starts to drag it and revert it back to usable Kinetic.Nodes when the drag-action has stopped?

At the moment I start caching on

stage.on('mousedown touchstart', function(){ // CACHING})

but the problem here is, that the user has to perform a second mousedown touchstart event to "grab" the cached image, which, of course, starts a new caching.

In this case my questions would be:

  1. How can I pass the mousedown touchstart event to the cached image, so the user can drag it with one fluent movement?

  2. How can I speed up caching? (It takes 1-2 seconds for the cached image to appear. Is it useful to cache it in a setInterval after every, lets say 4 secs, and use this precached image or causes that a too high performance drain?)

I highly appreciate any kind of suggestions regarding my problem or further tips&tricks to speed up things.

4

1 回答 1

2

基于此声明:

stage.on('mousedown touchstart', function(){ // CACHING})

我假设mousedown touchstart您打电话layer.toImage()stage.toImage()您想在单击/点击时拖动新图像。

  1. 您可以使用以下.startDrag()函数在新生成的图像上调用拖动事件:Kinetic.Shape#startDrag

    然后,您可以调用.stopDrag()onmouseup touchend来停止拖动。Kinetic.Shape#stopDrag

    就像是:

    var image, ox, oy;
    
    stage.on('mousedown touchstart', function(){
      // CACHING
      stage.toImage({
        width: stage.getWidth(),
        height: stage.getHeight(),
        callback: function(img) {
          var image = new Kinetic.Image({
            image: img,
            draggable: true
          });
          ox = image.getX();
          oy = image.getY();
          image.startDrag();
        }            
      });
    });
    
    stage.on('mouseup touchend', function(){
      image.stopDrag();
    
      //Calculate dx, dy to update nodes.
      var newX = image.getX();
      var newY = image.getY();
      var dx = newX-ox;
      var dy = newY-oy;
    
      var children = layer.getChildren();
      for (var i=0; i<children.length; i++) {
        children.setX(children.getX()+dx);
        children.setY(children.getY()+dy);
      }
    
      image.hide(); //or remove() or destroy()
      layer.draw();
    });
    

    请注意,您需要在拖动缓存层后更新原始节点。

    另一个注意事项我没有测​​试过代码,但我相信你可以按照我上面的内容做一些事情。

    小更新hide():拖动缓存的图层图像时,您还应该使用原始图层!:)show()当你隐藏缓存的图像层时,它会再次出现。

  2. 老实说,我不确定您将如何加快缓存时间,除非您可以预测用户何时需要单击/点击舞台移动。我认为您的建议会花费比节省更多的性能。

    我猜桌面缓存图像的速度比你的手机快?它可能只是 KineticJS 在移动和桌面上的性能限制......

更新

好的,我对#2有一个想法,它不完全是一个修复,但它可能对你更有效。

  1. mousedown将您的舞台活动与您的活动分开touchstartmousedown将是相同的,但touchstart我们想以不同的方式处理。

  2. 在舞台上touchstart,我们想像往常一样拖动整个舞台,但同时运行原始代码mousedown缓存图层。

  3. 缓存的图像完成加载(你说需要 1-2 秒)时,.stopDrag()在原始阶段使用并隐藏它。此时您要存储舞台的当前xy值,以便您仍然可以计算dx,dy。然后立即调用.startDrag()新的缓存图像并像我们为mousedown.

如何知道缓存图像何时完成加载?我认为这就是它的toImage() callback function用途。如果不是,那么希望 javascriptonload事件能够确定图像何时完成生成。

最终结果将是您将在舞台上缓慢地拖拽触摸事件,直到图像被缓存。然后我们翻转开关并停止拖动舞台,开始拖动缓存的图像,然后恢复/更新舞台touchend

希望这可以作为您问题的半解决方案...

另一个更新

好的,这是另一个实际上可能有助于您的表现的想法!

如果您的阶段不经常修改节点,您可以预先缓存阶段图像,以便它已经生成,并且.hide()它。那么当你需要拖动它时,你只需要设置缓存图像的x,y来匹配舞台当前的x,y然后.show()缓存图像。这将消除您第一次开始拖动时等待/加载缓存图像所需的时间。

如果您碰巧添加了一个节点或移动了一个节点或任何东西,那么在缓存图像之后。希望这是可管理的,因为我们不想过于频繁地缓存图像(降低性能)。同样,缓存的图像将提前为您的stage.drag活动做好准备。

目标是在您mousedown touchstart开始拖动之前缓存舞台。希望这会有所帮助。

于 2013-08-01T14:47:22.227 回答