2

抱歉,如果这个问题已经被问过,我试图找到它,但找不到。

我有一个画布,最终应该显示大约 400-500 个 20-30 像素高度/宽度的矩形。它们中的每一个都应该在鼠标上方和鼠标移出时向左和向上移动一个像素,以创建某种选定的行为。现在,我的代码适用于少量形状,但对于其中的 500 个形状,它开始显着减慢。从互联网上的一些示例中,我看到我可以创建“动画层”并将我需要动画的对象移动到那里。但是,这仍然需要我重新绘制主层以从之前的位置删除移动的项目......这是代码:

var seatMap = {};

seatMap.seatTypes = {
    economy: {
        width: 20,
        height: 20,
        fill: 'red',
        stroke: 'black',
        strokeWidth: 4,
        cornerRadius: 5
    },
    business: {
        width: 22,
        height: 22,
        fill: 'red',
        stroke: 'black',
        strokeWidth: 4,
        cornerRadius: 5
    },
    first: {
        width: 25,
        height: 25,
        fill: 'red',
        stroke: 'black',
        strokeWidth: 4,
        cornerRadius: 5
    }
};

seatMap.Map = function (params) {
    var stage = new Kinetic.Stage({
        container: params.container,
        width: params.width,
        height: params.height
    });

    var mainLayer = new Kinetic.Layer();
    var animationLayer = new Kinetic.Layer();

    stage.add(mainLayer);
    stage.add(animationLayer);

    var addSeat = function (object) {
        object.seat.mainLayerRef = mainLayer;
        object.seat.animationLayerRef = animationLayer;

        mainLayer.add(object.seat);
    };

    var refresh = function () {
        mainLayer.draw();
    }

    return {
        refresh: refresh,
        addSeat: addSeat
    }
}

seatMap.Seat = function (params) {

    var seatType = params.seatType == null ? seatMap.seatTypes.economy : params.seatType;

    var seat = new Kinetic.Rect({
        width: seatType.width,
        height: seatType.height,
        x: params.x,
        y: params.y,
        fill: seatType.fill,
        stroke: seatType.stroke,
        strokewidth: seatType.strokewidth,
        cornerRadius: seatType.cornerRadius,
        listening: true
    });
    seat.staticXPosition = params.x;
    seat.staticYPosition = params.y;

    seat.on('mouseover', function (event) {
        event.shape.moveTo(event.shape.animationLayerRef);
        event.shape.setX(event.shape.staticXPosition - 2);
        event.shape.setY(event.shape.staticYPosition - 2);
        event.shape.animationLayerRef.draw();
        event.shape.mainLayerRef.draw();
    });
    seat.on('mouseout', function (event) {
        event.shape.setX(event.shape.staticXPosition);
        event.shape.setY(event.shape.staticYPosition);
        event.shape.moveTo(event.shape.mainLayerRef);
        event.shape.animationLayerRef.draw();
        event.shape.mainLayerRef.draw();
    });

    return {
        seat: seat,
    }
}

以及呈现画布的代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="scripts/jquery-1.8.0.js"></script>
    <script type="text/javascript" src="scripts/kinetic-v3.10.5.min.js"></script>
    <script type="text/javascript" src="scripts/local/seatMapKineticExtender.js"></script>
    <!--<script type="text/javascript" src="scripts/local/app.js"></script>-->
    <script>
        $(function () {
            var map = new seatMap.Map({
                container: 'stage',
                width: 1000,
                height: 420
            });

            for (var i = 0; i < 800; i += 30) {
                for (var j = 0; j < 500; j+=30) {
                    var seat = new seatMap.Seat({
                        seatType: seatMap.seatTypes.business,
                        x: i,
                        y: j
                    });
                    map.addSeat(seat);
                }
            }
            //var seat = new seatMap.Seat({
            //    seatType: seatMap.seatTypes.business,
            //    x: 200,
            //    y: 200
            //});

            //map.addSeat(seat);
            map.refresh();
        });
    </script>
</head>
<body>
    <div id="stage" style="width: 1000px; height: 420px; margin: 0 auto; border: 1px solid black; position: relative">
        <div style="position: absolute; top: 0; z-index: 1000">
            <button id="zoomIn" type="button">Zoom In</button>
            <button id="zoomOut" type="button">Zoom Out</button>
        </div>

    </div>
</body>
</html>

我觉得我在这里做的很不对,但是,不幸的是我对 kineticjs 还不够熟悉。谁能指出我正确的方向?

在此先感谢,丹尼

4

3 回答 3

4

请查看 KineticJS v4.0.0,事件检测引擎已被重写,即使有数十万个形状,也会产生瞬时命中检测:

http://kineticjs.com/

于 2012-08-25T01:57:05.987 回答
2

好吧,这是一个很好的挑战。我认为问题在于形状事件,但那里的改进是如此之小。

KineticJS 中的事件通过搜索模型的坐标来应用于特定的屏幕形状,直到与当前鼠标坐标匹配。因此,通过只有一层,我们增加了要搜索的数组的大小。

解决方法是使用许多层。我为每一行添加了一个图层。

以下代码中的其他一些更改是:

  1. 不要在图层之间移动形状。它会导致数组拼接和索引移位。
  2. 使用相对move(x,y)方法而不是setX() setY()小班次的方法。
  3. 您在教程中阅读的动画层概念用于在定时帧间隔上执行实际动画。我们只是在一个事件上做一个正常的形状移动。
  4. 小的 JS 改进;返回对象隐藏私有数据和方法时,不要new用于创建对象。

<script>
    $(function () {
        var map = seatMap.Map({
            container: 'stage',
            width: 1000,
            height: 420
        });

        for (var i = 0; i < 800; i += 30) {
            var layer = map.createLayer();
            for (var j = 0; j < 500; j+=30) {
                var seat = seatMap.Seat({
                    seatType: seatMap.seatTypes.business,
                    x: i,
                    y: j
                });
                map.addSeat(seat, layer);
            }
            layer.draw();
        }
        //var seat = new seatMap.Seat({
        //    seatType: seatMap.seatTypes.business,
        //    x: 200,
        //    y: 200
        //});

        //map.addSeat(seat);
        map.refresh();
    });
</script>

代码

seatMap.Map = function (params) {
var stage = new Kinetic.Stage({
    container: params.container,
    width: params.width,
    height: params.height
});

var addSeat = function (object, layer) {
    object.seat.layer = layer;
    layer.add(object.seat);     
};

var refresh = function () {
    mainLayer.draw();
};

var createLayer = function() {
    var layer = new Kinetic.Layer();
    stage.add(layer);
    return layer;
};
return {
    createLayer : createLayer,
    refresh: refresh,
    addSeat: addSeat
};
}

seatMap.Seat = function (params) {

var seatType = params.seatType == null ? seatMap.seatTypes.economy : params.seatType;

var seat = new Kinetic.Rect({
    width: seatType.width,
    height: seatType.height,
    x: params.x,
    y: params.y,
    fill: seatType.fill,
    stroke: seatType.stroke,
    strokewidth: seatType.strokewidth,
    cornerRadius: seatType.cornerRadius,
    listening: true
});
seat.staticXPosition = params.x;
seat.staticYPosition = params.y;

seat.on('mouseover', function (event) {
    event.shape.move(-3,-3);
    event.shape.layer.draw();
});
seat.on('mouseout', function (event) {

    event.shape.move(3,3);
    event.shape.layer.draw();
});

return {
    seat: seat,
};
}
于 2012-08-23T00:40:55.757 回答
1

绘制 500 个形状就可以了。当然,性能还取决于计算机速度、浏览器(chrome 目前是最快的——但显然你需要在所有浏览器上都有可接受的性能)。

查看有关性能和改进方法的链接。

于 2012-08-22T21:32:32.760 回答