如何在dragstart之前缓存整个图层并将其恢复为dragend?

时间:2013-07-31 14:59:17

标签: html5 performance caching html5-canvas kineticjs

我目前正试图加快移动设备的网络应用程序速度,但现在我陷入了最重要的部分 - 缓存。如何在用户开始拖动它之前缓存整个图层,并在拖动操作停止时将其恢复为可用的Kinetic.Nodes?

目前我开始缓存

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

但问题在于,用户必须执行第二个mousedown touchstart事件来“抓取”缓存的图像,当然,这会启动新的缓存。

在这种情况下,我的问题是:

  1. 如何将mousedown touchstart事件传递给缓存图像, 那么用户可以用一个流畅的动作拖动它吗?

  2. 如何加快缓存速度? (缓存图像显示需要1-2秒。在每次缓存后,将它缓存在setInterval中是否有用,比方说4秒,并使用此预先缓存的图像或导致性能过高导致?)

  3. 我非常感谢有关我的问题的任何建议或进一步的提示和技巧,以加快速度。

1 个答案:

答案 0 :(得分:2)

基于此声明:

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

我假设在mousedown touchstart上您拨打layer.toImage()stage.toImage(),并且您希望在点击一下/点击时拖动新图片。

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

    然后,您可以在.stopDrag()上调用mouseup 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. 老实说,我不确定如何加快缓存时间,除非您可以预测用户何时需要点击/点按要移动的阶段。我认为你的建议会比它节省的成本更高。

    我猜测桌面缓存图像比在手机上更快?它可能只是在Mobile vs Desktop上对KineticJS性能的限制......

  3. <强>更新

    好的,我对#2 有一个想法,这不是一个修复,但它可能对你有用。

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

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

    3. 缓存图片完成加载时(您说需要1-2秒),请在原始阶段上使用.stopDrag()并隐藏它。此时您想要存储舞台的当前 x y 值,这样您仍然可以计算 dx,dy 。然后立即在新的缓存图片上调用.startDrag(),然后像我们为mousedown所做的那样继续。

    4. 如何知道缓存图片何时完成加载?我认为这是toImage() callback function的用途。如果没有,希望javascript onload事件可用于确定图像何时完成生成。

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

      希望这可以解决您的问题......

      另一个更新

      好的,这是另一个可能对您的表现有帮助的想法!

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

      如果您确实添加了节点或移动节点或其他任何内容,则在缓存图像之后。希望这是可管理的,因为我们不希望缓存图像太频繁(消耗性能)。此外,缓存的图片将事先为您的stage.drag事件做好准备。

      目标是在执行mousedown touchstart之前缓存阶段并开始拖动。希望这会有所帮助。