【问题标题】:How to avoid event's lag with KineticJS?如何避免事件与 KineticJS 的滞后?
【发布时间】:2014-01-19 21:40:42
【问题描述】:

我正处于为混合网络/文本冒险游戏制作 2d 地图构建器的原型设计阶段,到目前为止 KineticJS 似乎是一个理想的选择。当前唯一的问题是,如果鼠标移动速度足够快,它将跳过单元格并且永远不会触发其 mouseover 事件处理程序。

2 核心功能目标:当用户突出显示一个单元格时,它将被标记为“活动”。此外,如果他们按住鼠标并在网格上移动,则单元格将被打开或关闭(如果第一个单元格未处于活动状态,则这可能会被重构为全部打开,反之亦然)。

我的问题:有没有办法确保所有单元格都被触发,而不管鼠标光标速度如何?如果没有,是否有更好的方法在单元格上画一条线,以便始终触发所有相关单元格?

整个原型已放入 jsFiddle (http://jsfiddle.net/7ggS4/),但为了将来,其余部分也将复制到下面。

    <head>
    <title>KineticJS</title>
    <script src="//cdnjs.cloudflare.com/ajax/libs/kineticjs/4.7.2/kinetic.min.js"></script>
</head>
<body>
    <div id="canvas"></div>
</body>
<script defer="defer">


    /**
    Return's a KS layer

    */
    function Grid(cells, stage) {
        //Constants
        // Illrelevant comment - It seriously pisses me off that canvas uses
        // string color codes ( either name or string hexidecimal ) instead of taking an
        // integer or actual hexidecimal 0xFFFF values.  This just seems painfully inefficient.
        this.activeCellColor = "green";
        this.clearCellColor = "blue";
        this.highlightCellColor = "red";

        this.cells = cells,
        this.layer = new Kinetic.Layer(),
        this.grid = new Array(),
        this.isMouseDown = false,
        this.mouseLeft = false,
        this.mouseRight = false,
        this.adjRow = stage.getWidth() / cells,
        this.adjCol = stage.getHeight() / cells;
        this.generate();
        stage.add(this.layer)

    }

    Grid.prototype.generate = function(){
        var i, rx, ry, rect;

        for (i = 0; i < this.cells * this.cells; i++) {
            rx = Math.floor(i / this.cells) * this.adjRow;
            ry = (i % this.cells) * this.adjCol;

            rect = new Kinetic.Rect({
                x: rx,
                y: ry,
                width: this.adjRow,
                height: this.adjCol,
                fill: this.clearCellColor,
                stroke: 'black',
                strokeWidth: .2,
                cell: {x: Math.floor(i / this.cells), y: i % this.cells},
                active: false,
                grid: this //Just in case .bind(this) doesn't work right
            });
            rect.on('mouseenter', this.onMouseEnter.bind(this));
            rect.on('mouseleave', this.onMouseLeave.bind(this));
            rect.on('mousedown', this.onMouseDown.bind(this));
            rect.on('mouseup', this.onMouseUp.bind(this));

            this.grid.push(rect);
            this.layer.add(rect);

        }

    }

    Grid.prototype.onMouseEnter = function(evt) {
        var src = evt.targetNode;
        console.log(evt.type, this.isMouseDown, src.attrs.cell)

        if (this.isMouseDown == true) {
            src.attrs.active = ! src.attrs.active;
        }

        if (src.attrs.active == false) {
            src.setFill(this.highlightCellColor);
        } else {
            src.setFill(this.activeCellColor);
        }

        this.layer.batchDraw();
    }

    Grid.prototype.onMouseLeave = function(evt) {
        var src = evt.targetNode;
        console.log(evt.type, this.isMouseDown, src.attrs.cell)

        if (src.attrs.active == false) {
            src.setFill(this.clearCellColor);
            this.layer.batchDraw();
        }

    }

    Grid.prototype.onMouseUp = function(evt){
        var src = evt.targetNode;
        console.log(evt.type, this.isMouseDown, src.attrs.cell)
        this.isMouseDown = false;
    }

    Grid.prototype.onMouseDown = function(evt){
        var src = evt.targetNode;
        console.log(evt.type, this.isMouseDown, src.attrs.cell)
        this.isMouseDown = true;
        src.attrs.active = ! src.attrs.active;

        if (src.attrs.active) {
            src.setFill(this.activeCellColor);
        } else {
            src.setFill(this.clearCellColor);
        }
        this.layer.batchDraw();
    }



    var stage = new Kinetic.Stage({
        container: 'canvas',
        width: 600,
        height: 600
      }),

    myGrid = new Grid(50, stage);

</script>

【问题讨论】:

    标签: javascript html5-canvas dom-events kineticjs


    【解决方案1】:

    50x50=2500 个活动对象:这对于 Kinetic 来说太多了。

    请记住,每个“智能”动力学单元都有很多与之相关的开销。

    将网格缩小到 20x20 怎么样?

    或者,您必须将鼠标处理与单元格处理分开,以获得所需的性能。

    鼠标处理

    您的鼠标处理只涉及将鼠标点捕获到累积点数组中。您可以使用这种代码来捕获舞台上的鼠标点:

    $(stage.getContent()).on('click', function (event) {
        myPointsArray.push(stage.getMousePosition());
    });
    

    细胞处理

    单元格处理将涉及应用这些累积点来影响您的网格单元格。执行此代码的有效位置是 requestAnimationFrame (RAF) 循环。您不会制作动画,但 RAF 提供高性能,因为它知道系统资源的可用性。 RAF 循环如下所示:

    function processPointsArray(array){
    
        // request another loop even before we're done with this one
        requestAnimationFrame(processPointsArray);
    
        // process the points array and affect your cells here
    
    }
    

    A处理效率

    RAF 每秒最多调用 60 次,因此您的用户在此期间可能只会浏览您网格的一小部分。您可以通过计算累积点数组中的最小/最大 x 和 y 坐标来提高性能,并且只处理该边界内的那些网格单元。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-13
      相关资源
      最近更新 更多