如何在 dragstart 之前缓存整个图层并将其还原回 dragend?

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

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?

目前我开始缓存

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

但这里的问题是,用户必须执行第二个 mousedown touchstart 事件来抓取"缓存的图像,这当然会启动新的缓存.

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. 如何将 mousedown touchstart 事件传递给缓存的图像,这样用户就可以用一个流畅的动作拖动它?

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

如何加快缓存速度?(缓存的图像需要 1-2 秒才能出现.在每次之后将其缓存在 setInterval 中是否有用,比如说 4 秒,并使用此预缓存的图像或导致性能太高排水?)

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.

推荐答案

基于此声明:

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

我假设在 mousedown touchstart 你调用 layer.toImage()stage.toImage() 并且你想拖动单击/点击时的新图像.

I'm assuming that on mousedown touchstart you call layer.toImage() or stage.toImage() and you want to drag the new image on that one click/tap.

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

  1. You can invoke the drag event on the new generated image by using the .startDrag() function: Kinetic.Shape#startDrag

然后您可以在 mouseup touchend 上调用 .stopDrag() 来停止拖动.Kinetic.Shape#stopDrag

You can then invoke .stopDrag() on mouseup touchend to stop the drag. 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();
});

注意拖动缓存层后需要更新原始节点.

Note you need to update your original nodes after dragging the cached layer.

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

Another Note I haven't tested the code but I believe you could do something along the lines of what I've got up there.

小更新:您还应该在拖动缓存的图层图像时hide()原始图层!:) 然后 show() 当你隐藏缓存的图像层时再次显示它.

Small UPDATE: You also should probably hide() the original layer while dragging the cached layer image! :) And then show() it again when you hide the cached image layer.

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

Honestly I'm not sure how you would speed up that cache time unless you can predict when the user needs to click/tap the stage to move. I think your suggestion would cost more performance than it would save.

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

I'm guessing that the desktop caches the image faster than on your mobile? It might fall into just being a limitation of KineticJS performance on Mobile vs Desktop...

更新

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

Okay, I have an idea for #2, it's not exactly a fix but it might work better for you.

  1. 将舞台 mousedown 事件与 touchstart 事件分开.mousedown 将是相同的,但 touchstart 我们想要以不同的方式处理.

  1. Separate your stage mousedown event with your touchstart event. mousedown will be the same but touchstart we want to handle differently.

在舞台 touchstart 我们想像平常一样拖动整个舞台,但同时运行原始 mousedown 以缓存图层.

On stage touchstart we want to drag the entire stage like normal, but meanwhile run the code for the original mousedown to cache the layer.

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

When the cached image finishes loading (takes 1-2 seconds you say), use .stopDrag() on the original stage and hide it. At this moment you want to store the current x and y values of the stage, so that you can still calculate dx,dy. Then immediately call .startDrag() on the new cached image and continue on like we did for mousedown.

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

How to know when the cached image finishes loading? I think that's what the toImage() callback function is for. If not, than hopefully a javascript onload event will work to determine when the image finishes generating.

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

The end result will be that you'll get your slow choppy drag on the stage for touch events UNTIL the image is cached. Then we flip the switch and stop dragging the stage, start dragging the cached image, and then revert/update the stage on touchend.

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

Hope that works as a semi-solution to your problem...

另一个更新

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

Okay here's another idea that actually might help your performance!

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

If your stage isn't modifying nodes very often, you can pre-cache the stage image so that it's already generated, and .hide() it. Then when you need to drag it, you just need to set the x,y of the cached image to match the stage's current x,y and then .show() the cached image. This will eliminate the time needed to wait/load the cached image when you first start dragging.

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

If you do happen to add a node or move a node or anything, after that cache the image. Hopefully this is manageable as we don't want to cache the image too often (drains performance). Again the cached image will be ready for your stage.drag event beforehand.

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

The goal is to have the stage cached before you do mousedown touchstart and start dragging. Hopefully this helps.

相关文章