KineticJS - Moving 4000 tiles with Stage.draggable

大憨熊 提交于 2019-12-10 21:03:52

问题


(Sorry if this is a duplicate, but I don't think it is)

Just so you know, I'm using Google Chrome 29.0.1547.66 m.

I have a KineticJS Project going on at the moment which builds a tiled "staggered" map 40 x 100 tiles. The map takes about 500ms to render which is fine. All 4000 tiles have been put onto one layer.

Once that has completed, I try to drag the stage but I am getting very poor performance as it tries to move all 4000 tiles at once. We are talking about 160ms of CPU time.

I have tried breaking each row up into its own separate layer as others suggested, but that made it even worse (620ms CPU time) as it had to move each layer separately.

I wouldn't say I'm very good at JavaScript but I can't see a way to improve the performance of the drag and I have done some descent research.

Maybe caching the entire layer or something could work?

The project so far has quite a lot of code, so I'm just going to show snippets:

//Stage Object
window.stage = new Kinetic.Stage({
    container: element,
    width: 800,
    height: 600,
    draggable: true
});

//Map Loop for create and position tiles
var tempLayer = map.addLayer(); //makes a new layer and adds it to stage etc.
for (var y = 0; y < height; y++) { //100 tiles high
    for (var x = width-1; x > -1; x--) { //40 tiles wide
        var tileImg = map._tiles[mapArray[x][y]-1]; //map._tiles is just an array of Kinetic.Image objects
        if (typeof(tileImg) != "undefined"){
            var tileClone = tileImg.clone();
            map.place(x, y, 0, tileClone, tempLayer); //places tile in world scope positions
        }
    }
}
tempLayer.draw();

If I can't work out how to improve the performance, there is no way anyone will be able to run this and the project is going to have to be binned, so all thoughts are appreciated! Thanks!


回答1:


Have a look at this SO Question: How to cache a whole layer right before dragstart and revert it back on dragend?

The question and my answer describes a similar issue and I think the solution I came up with may help.

Basically what I was suggesting (although I haven't tried it completely so I don't know if it will work well):

  1. Cache the layer using toImage
  2. Drag the image on a different layer while hiding the original layer.
  3. Calculate dx and dy (the distance that you moved)
  4. Update the original layer with dx and dy
  5. Hide image layer, show shapes layer.

I managed to create a quick example JSFIDDLE to work with so check it out. One thing I noticed is that the stage size really affected the performance of the drag, even if it was just 1 rectangle instead of 4000. So, if the stage is really big, even with this image caching thing it didn't really help. But when I decrease the stage size it seems to help

UPDATE:

I found the reason for that "stretched/scaled" image when dragging. It's because I had the image size set statically like so:

var image = new Kinetic.Image({
    image: img,
    x: 0,
    y: 0,
    width: 2000,
    height: 5000
});

This caused the image to stretch since the image was larger than the stage. If we remove the width and height properties like so:

var image = new Kinetic.Image({
    image: img,
    x: 0,
    y: 0
});

You'll see that the image doesn't stretch anymore.

The other good news is that I reduced the stage dimensions by half (although the number of rectangles, area taken by rectangles and size of image remains the same) and the performance has improved greatly. Hopefully your stage dimension isn't as large (2000x5000) as I had it before right? Check the JSFIDDLE now and see it in action!



来源:https://stackoverflow.com/questions/18786085/kineticjs-moving-4000-tiles-with-stage-draggable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!