rotate to mouse kinetic js

2019-08-23 06:14发布

I looked at many examples but so far nothing worked. I want the circle to rotate on mousemove and it is rotating centered, so no problems so far. But, it does a 180 jump when I pass half of the stage. So everything is fine till I pass the half of the stage, clearly I'm missing something. Math.atan2 gives me an error: the circle jumps to the (0,0) of the stage.

Please help I really need this badly.

Thanks in advance!

new Kinetic.Tween({
  node: cGrad1, 
  x: stage.getWidth()/2, 
  y: stage.getHeight()/2,
  duration: 1,
  opacity:1,
  easing: Kinetic.Easings.EaseInOut
}).play();

clickO.on('mousemove', function() {  
  for(var n = 0; n < 16; n++) {
    var shape = cGradlayer1.getChildren()[n];
    var stage = shape.getStage();
    var mousePos = stage.getMousePosition();
    var x =  mousePos.x - shape.getPosition().x;
    var y = mousePos.y -shape.getPosition().y ;
    var degree = (Math.PI)+(Math.atan(y/x));

    shape.setAttrs({
      rotation: degree
    })
    cGradlayer1.draw()
  }
})

2条回答
smile是对你的礼貌
2楼-- · 2019-08-23 06:24

Well this is what I came up with, and hopefully it's close to what you were looking for: jsfiddle

Basically, to calculate the angle you want to rotate to, we need to store two points:

  1. The origin of the shape (centre coordinate)
  2. The coordinate of the mouse click

Once you have that, you can calculate the angle between the two points with a little bit of trigonometry (Sorry if I am not accurate here, Trigonometry is not my strong suit). Calculate the distance between the two points (dx, dy) and then use the trig formula to find the angle in degrees.

layer.on('click', function() {
  var mousePos = stage.getMousePosition();
  var x = mousePos.x;
  var y = mousePos.y;
  var rectX = rect.getX()+rect.getWidth()/2;
  var rectY = rect.getY()+rect.getHeight()/2;
  var dx = x - rectX;
  var dy = y - rectY;
  var rotation = (Math.atan2(dy, dx)*180/Math.PI+360)%360;

  var rotateOnClick = new Kinetic.Tween({
    node: rect,
    duration: 1,
    rotationDeg: rotation,
    easing: Kinetic.Easings.EaseInOut
  });
  rotateOnClick.play();
});

EDIT:

Based off the gathered information below (which I came to the same conclusion as) I have updated my fiddle: jsfiddle

As markE mentioned below in the comments, KineticJS does not support "force-clockwise flag", so the rotation always jumps when rotating past 360 in the clockwise direction, or past 0 in the counter clockwise position. Otherwise, we know that the rotation works properly.

So, to fix this manually there are two cases we need to consider:

  1. When we rotate past 360 in the clockwise direction.
  2. When we rotate past 0 in the counter clockwise direction.

And this is the math I used to calculate whether to counter the rotation or not:

var currentDeg = rect.getRotationDeg();

var oneWay = rotation - currentDeg;
var oneWayAbsolute = Math.abs(rotation - currentDeg);
var otherWay = 360-oneWayAbsolute;

if (otherWay < oneWayAbsolute) { 
    //Take the other way
    if (oneWay > 0) {
        //Clicked direction was positive/clockwise
        var trueRotation = currentDeg - otherWay;
    } else {
        //Clicked direction was negative/counter clockwise
        var trueRotation = currentDeg + otherWay;
    }
} else {
    //Take the clicked way
    var trueRotation = rotation;
}

Basically we want to figure out which way to rotate, by comparing the angle degrees of which direction would be closer, the direction we clicked in, or the opposite way.

If we determined that the otherWay was closer to the currentDeg, then we need to see if the direction we clicked in was in the counter clockwise (negative) or clockwise (positive) direction, and we set the otherWay direction to go in the opposite direction.

And then you can normalise the rotationDeg onFinish event.

var rotateOnClick = new Kinetic.Tween({
    node: rect,
    duration: 1,
    rotationDeg: trueRotation,
    easing: Kinetic.Easings.EaseInOut,
    onFinish: function() {
        trueRotation = (trueRotation+360)%360;
        rect.setRotationDeg(trueRotation);
        layer.draw();
    }
});
查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-08-23 06:38

You might need to set the x and y position of the Tween as follows:

new Kinetic.Tween({
  x: mousePos.x,
  y: mousePos.y,
  node: shape, 
  rotation: degree,
  easing: Kinetic.Easings.EaseInOut,
  duration:1,
}).play();

See this tutorial for reference http://www.html5canvastutorials.com/kineticjs/html5-canvas-stop-and-resume-transitions-with-kineticjs/

查看更多
登录 后发表回答