图层旋转后KineticJS鼠标位置错误

时间:2013-08-09 05:26:04

标签: html5-canvas kineticjs

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

  1. 首先,在蓝框中画一些东西。
  2. 然后,单击一次旋转按钮。
  3. 旋转框后,再画一些东西。
  4. 最后画的poisitoin错了。
  5. 我该如何解决这个问题,谢谢!

    代码:

    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 = [];
    });
    

1 个答案:

答案 0 :(得分:5)

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

那是因为你要求stage.getMousePosition而舞台不会轮换。

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

enter image description here

如果将图层旋转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>