kineticjs以鼠标角度旋转

时间:2013-02-18 15:23:23

标签: javascript rotation kineticjs mouse-position

我正在尝试根据鼠标在该图像上单击以及鼠标在对象中心的角度来旋转图像对象。

考虑一个单位圆,并根据鼠标在该圆上的位置围绕圆圈旋转图像。

我目前有

var stage = new Kinetic.Stage({
container: "container",
width: 800,
height: 500,
id: "myCanvas",
name: "myCanvas"
});
var layer = new Kinetic.Layer();
//gets the canvas context
var canvas = stage.getContainer();
var mousePosX;
var mousePosY;
var mouseStartAngle;
var selectedImage;
var mouseAngle;
var mouseStartAngle;
console.log(canvas)

var shiftPressed
window.addEventListener('keydown', function (e) {
if (e.keyCode == "16") {
    shiftPressed = true;
}
console.log(shiftPressed)
}, true);

window.addEventListener('keyup', function (e) {
if (e.keyCode == "16") {
    shiftPressed = false;
}
console.log(shiftPressed)
}, true);

function drawImage(imageObj) {

var dynamicImg = new Kinetic.Image({
    image: imageObj,
    x: stage.getWidth() / 2 - 200 / 2,
    y: stage.getHeight() / 2 - 137 / 2,
    width: 100, //imageObj.width,
    height: 100, // imageObj.height,
    draggable: true,
    offset: [50,50] //[(imageObj.width/2), (imageObj.height/2)]

});

dynamicImg.on('mousedown', function () {


    selectedImage = this;
    console.log("x: " + this.getX())
    console.log("y: " + this.getY())

    var mouseStartXFromCenter = mousePosX - (this.getX() + (this.getWidth() / 2));
    var mouseStartYFromCenter = mousePosY - (this.getY() + (this.getHeight() / 2));
    mouseStartAngle = Math.atan2(mouseStartYFromCenter, mouseStartXFromCenter);

    if (shiftPressed) {
        //console.log("trying to switch draggable to false");
        //console.log(this)
        this.setDraggable(false);
    }
});

dynamicImg.on('mouseup mouseout', function () {
    //console.log('mouseup mouseout')
    this.setDraggable(true);
});


dynamicImg.on('mouseover', function () {
    document.body.style.cursor = 'pointer';
});
dynamicImg.on('mouseout', function () {
    document.body.style.cursor = 'default';
});

imageArray.push(dynamicImg);
layer.add(dynamicImg);
stage.add(layer);
}
var imageObj = new Image();
imageObj.onload = function () {
drawImage(this);

};
imageObj.src = 'http://localhost:60145/Images/orderedList8.png';

function getMousePos(evt) {

var rect = canvas.getBoundingClientRect();
return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
};
}


canvas.addEventListener('mouseup', function () {
selectedImage = undefined;
});

canvas.addEventListener('mousemove', function (evt) {
mousePos = getMousePos(evt);
//console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y)
mousePosX = mousePos.x;
mousePosY = mousePos.y;

if (selectedImage != undefined) {

    mouseXFromCenter = mousePosX - selectedImage.getX();
    mouseYFromCenter = mousePosY - selectedImage.getY();
    mouseAngle = Math.atan2(mouseYFromCenter, mouseXFromCenter);

    var rotateAngle = mouseAngle - mouseStartAngle;

    selectedImage.setRotation(rotateAngle);

}
}, false);

代码有几个方面。 - 如果按下'shift'并且mousedown事件发生在图像上,它应该只允许旋转。

- 它需要维护动态图像绘制,因为它们将在页面的整个生命周期中动态填充画布。

这是我想要发生的类似事情的一个很好的例子,但只是简单地无法让它在canvas / kineticjs中工作。 http://jsfiddle.net/22Feh/5/

3 个答案:

答案 0 :(得分:1)

我会更简单地使用dragBoundFunc。 http://jsfiddle.net/bighostkim/vqGmL/

dragBoundFunc: function (pos, evt) {
    if (evt.shiftKey) {
        var x = this.getX() - pos.x;
        var y = this.getY() - pos.y;
        var radian = Math.PI + Math.atan(y/x);
        this.setRotation(radian);
        return {
            x: this.getX(),
            y: this.getY()
        }
     } else {
        return pos;
     }
}

答案 1 :(得分:0)

您应该更清楚.on()事件的作用。在您的代码中,除了计算mouseStartAngle之外,形状上的mousedown不会执行任何操作,但不会执行任何操作。并且你在shape事件上的mouseUp也没有做太多。这是你的浏览器/客户端mousedown / mouseup完成所有工作,这就是为什么它在一些点击而不是其他点击时正确旋转的原因。

要设置旋转,您有很多选项,这里有两个:

选项一:在mousedown上手动设置弧度

  dynamicImg.on('mousedown', function () {   
    dynamicImg.setRotation(mouseStartAngle); //set the rotation degree
    layer.draw(); // redraw the layer
  }

选项二:让kineticJS为您设置旋转动画

  dynamicImg.on('mousedown', function () { 
    dynamicImg.transitionTo({  
        duration: 1,       // length of animation in seconds
        rotation: mouseStartAngle   // your angle, in radians
    });
  }

您更新的jsfiddle:http://jsfiddle.net/WXHe6/1/

以下是一些补充说明:

你遇到麻烦的原因是因为你的代码结构有点混乱,不好意思。您正在混合浏览器事件并将监听器添加到画布而不是使用内置的kineticJS功能,例如,您可以使用stage.getUserPosition()来获取鼠标坐标。除非你迫切需要以这种方式构建项目,否则尽量避免使用它。

我喜欢的是你已经创建了分解代码的函数,但是在不同的方面你有多个函数做同样的事情,比如计算和更新旋转角度。为什么不用一个函数来获得角度呢?

一些提示:

  1. 尝试主要使用KineticJS功能(我知道你需要SHIFT等按钮的事件监听器)。我的意思是,使用像stage.getUserPosition();获得鼠标/触摸坐标,而不是evt.clientX,它更干净,已经为你完成了工作,无需重新发明轮子。

  2. 设置一个用于设置/获取形状旋转的功能。然后你可以随时调用它。 (使用较少的重复代码)

  3. 如果您不希望在单击shift时可以拖动形状,则应在单击项目之前设置该形状。您有按钮侦听器,因此您可以在按下shift时禁用所有形状的旋转,或者只为光标下的形状禁用旋转。

  4. imageArray.push(dynamicImg);不确定你是否真的需要这个,如果你需要作为一个数组访问所有元素,你总是可以做layer.getChildren();获取图层中的所有图像,或者以数字方式访问它们,如layer.getChildren()[0]; (按创建顺序)

答案 2 :(得分:0)

我的错误,我误解了你的问题。你基本上缺少一行:

    layer.draw();

按住shift并移动鼠标,你会看到它旋转得很好。 http://jsfiddle.net/WXHe6/2/

    canvas.addEventListener('mousemove', function (evt) {
            mousePos = getMousePos(evt);
            //console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y)
            mousePosX = mousePos.x;
            mousePosY = mousePos.y;

            if (selectedImage != undefined) {

            mouseXFromCenter = mousePosX - selectedImage.getX();
            mouseYFromCenter = mousePosY - selectedImage.getY();
            mouseAngle = Math.atan2(mouseYFromCenter, mouseXFromCenter);

            var rotateAngle = mouseAngle - mouseStartAngle;

            selectedImage.setRotation(rotateAngle);
            layer.draw(); // <--------------- right here
  }
  }, false);