【问题标题】:KineticJS mouse position wrong after layer rotated图层旋转后KineticJS鼠标位置错误
【发布时间】:2013-08-11 00:29:54
【问题描述】:

我的演示在这里http://jsfiddle.net/akuma/7NmXw/1/

  1. 首先,在蓝色框中画一些东西。
  2. 然后,单击一次旋转按钮。
  3. 框旋转后,再次绘制一些东西。
  4. 最后draw poisitoin 错了。

如何解决这个问题,谢谢!

代码:

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

var layer = new Kinetic.Layer({
    width: 400,
    height: 400
});

var rect = new Kinetic.Rect({
    x: 0,
    y: 0,
    width: 400,
    height: 300,
    fill: '#00D2FF',
    stroke: 'black',
    strokeWidth: 5
});

layer.add(rect);
stage.add(layer);

$(document).on('click', '#rotateBtn', function () {
    var w = layer.getWidth(),
        h = layer.getHeight();
    layer.setOffset(w / 2, h / 2);
    layer.setPosition(w / 2, h / 2);
    layer.rotateDeg(90);
    layer.draw();
});

var points = [],
    drawing = false;

stage.on('mousedown', function () {
    drawing = true;

    var pos = stage.getMousePosition();
    points.push([pos.x, pos.y]);

    var line = new Kinetic.Line({
        id: 'line',
        points: [
            [pos.x, pos.y],
            [pos.x + 1, pos.y + 1]
        ],
        stroke: 'white',
        strokeWidth: 5,
        lineCap: 'round',
        lineJoin: 'round'
    });

    layer.add(line);
    layer.drawScene();
});

stage.on('mousemove', function () {
    if (!drawing) {
        return;
    }

    // Remove previous line
    layer.get('#line').remove();

    var pos = stage.getMousePosition();
    points.push([pos.x, pos.y]);

    // Redraw line
    var line = new Kinetic.Line({
        id: 'line',
        points: points,
        stroke: 'white',
        strokeWidth: 5,
        lineCap: 'round',
        lineJoin: 'round'
    });
    layer.add(line);
    layer.drawScene();
});

stage.on('mouseup', function () {
    drawing = false;
    points = [];
});

【问题讨论】:

    标签: html5-canvas kineticjs


    【解决方案1】:

    即使在旋转之后,Kinetic 仍会为您提供未旋转的鼠标坐标

    那是因为你要求 stage.getMousePosition 并且舞台没有旋转。

    没有像 layer.getMousePosition 这样的方法,所以你必须创建一个。

    如果您将图层旋转 90 度,您还必须将舞台的鼠标坐标旋转 90 度。

    以下是旋转舞台鼠标位置以匹配图层旋转的方法:

        // get the unrotated mouse position from Kinetic
    
        var pos=stage.getMousePosition();
    
        // rotate that point to match the layer rotation
    
        var x1 = rotationX 
                  + (pos.x-rotationX)*rotationCos 
                  + (pos.y-rotationY)*rotationSin;
    
        var y1 = rotationY 
                  + (pos.y-rotationY)*rotationCos 
                  - (pos.x-rotationX)*rotationSin;
    

    由于您将在每次鼠标移动时进行此数学运算,因此您应该预先计算旋转值以最大限度地提高性能:

        // reset the current rotation information
    
        function setRotation(degrees){
            var radians=layer.getRotation();
            rotationX=layer.getOffsetX();
            rotationY=layer.getOffsetY();
            rotationCos=Math.cos(radians);
            rotationSin=Math.sin(radians);
        }
    

    另外,你的问题有点离题,但是......

    您可以“回收”现有的行,而不是在每次鼠标移动时删除/重新创建新行:

      // set the points property of the line to your updated points array
    
      line.setPoints(points);
    

    这是代码和小提琴:http://jsfiddle.net/m1erickson/cQATv/

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Prototype</title>
        <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
        <script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.5.min.js"></script>
    
    <style>
    #container{
      border:solid 1px #ccc;
      margin-top: 10px;
      width:400px;
      height:400px;
    }
    </style>        
    <script>
    $(function(){
    
        var stage = new Kinetic.Stage({
            container: 'container',
            width: 500,
            height: 500
        });
        var layer = new Kinetic.Layer({width:400,height:400});
        stage.add(layer);
    
    
        // vars to save the current rotation information
        var rotationX;
        var rotationY;
        var rotationCos;
        var rotationSin;
        setRotation(0);
    
    
        var rect = new Kinetic.Rect({
            x: 0,
            y: 0,
            width: 400,
            height: 300,
            fill: '#00D2FF',
            stroke: 'black',
            strokeWidth: 5
        });
    
        layer.add(rect);
        stage.add(layer);
    
        $(document).on('click', '#rotateBtn', function () {
            var w = layer.getWidth(),
                h = layer.getHeight();
    
            layer.setOffset(w / 2, h / 2);
            layer.setPosition(w / 2, h / 2);
            layer.rotateDeg(90);
            layer.draw();
    
            // set the info necessary to un-rotate the mouse position
            setRotation(layer.getRotationDeg())
    
        });
    
        var points = [],
            drawing = false;
    
        stage.on('mousedown', function () {
            drawing = true;
    
            // get the rotated mouse position
            pos=getPos();
            points.push([pos.x, pos.y]);
    
            var line = new Kinetic.Line({
                id: 'line',
                points: [
                    [pos.x, pos.y],
                    [pos.x + 1, pos.y + 1]
                ],
                stroke: 'white',
                strokeWidth: 5,
                lineCap: 'round',
                lineJoin: 'round'
            });
    
            layer.add(line);
            layer.drawScene();
        });
    
        stage.on('mousemove', function () {
            if (!drawing) {
                return;
            }
    
            // Remove previous line
            layer.get('#line').remove();
    
            // get the rotated mouse position
            var pos = getPos();
            points.push([pos.x, pos.y]);
    
            // Redraw line
            var line = new Kinetic.Line({
                id: 'line',
                points: points,
                stroke: 'white',
                strokeWidth: 5,
                lineCap: 'round',
                lineJoin: 'round'
            });
            layer.add(line);
            layer.drawScene();
    
        });
    
        stage.on('mouseup', function () {
            drawing = false;
            points = [];
        });
    
    
        // reset to the current rotation information
        function setRotation(degrees){
            var radians=layer.getRotation();
            rotationX=layer.getOffsetX();
            rotationY=layer.getOffsetY();
            rotationCos=Math.cos(radians);
            rotationSin=Math.sin(radians);
        }
    
    
        // rotate the stage mouse position
        // to match the layer rotation
        function getPos(x,y){
    
            // normal space, no adjustment necessary
            if(rotationCos==0){return;} 
    
            var pos=stage.getMousePosition();
    
            var x1 = rotationX 
                      + (pos.x-rotationX)*rotationCos 
                      + (pos.y-rotationY)*rotationSin;
    
            var y1 = rotationY 
                      + (pos.y-rotationY)*rotationCos 
                      - (pos.x-rotationX)*rotationSin;
    
            return({x:x1,y:y1});
        }
    
    
    }); // end $(function(){});
    
    </script>       
    </head>
    
    <body>
        <button id="rotateBtn">rotate</button>
        <div id="container"></div>
    </body>
    </html>
    

    【讨论】:

    • 谢谢!这很好用。我之前使用过 line.setPoints(points) ,但它使绘图有点延迟。我不知道为什么。
    猜你喜欢
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-23
    • 2014-10-18
    相关资源
    最近更新 更多