Reputation: 357
I'd like to rotate an Image about an absolute rotate point with kinectJS. For example about
var rotatePoint = {x: 500, y: 500}
The rotation schould be initialised by clicking at the image and moving the mouse, i.e. by dragging and dropping the image. Therby it schould rotate about the same angle, the mouse is drawing.
Yesterday I worked all day at this problem an coudn't find a solution.
Any ideas?
Thanks!
Upvotes: 0
Views: 626
Reputation: 357
Thank you!
I finaly got the clue. In the following sample-code the image imgObj rotates about
imgObj.rotPoint = {x: 500, y: 500}
There where several problems to solve: You can't just set an absolute rotate point, you have to change the offset relative to its standard-position (upper left edge of the image). Then you have to move the image back, because the change of the offset moved the image.
For the roation I enabled dragging and used a dragBoundFunc.
Setting
return {x: this.getAbsolutePosition().x, y: this.getAbsolutePosition().y};
will asure you, that there will be no real dragging - just rotation.
For the rotation itself you need six values: Three values at the beginning of the dragging:
I get these values by binding onmousedown and by just using these values if there is a dragging and dropping.
Three values that change all the time while dragging and dropping:
I get these values in my dragBoundFunc.
While using Math.atan2() for getting the angles, you have to concern, that you're not in an x-y-coordinatesystem but in an x-(-y)-coordinatesystem - so use: Math.atan2(-y,x).
By subtracting radMouseStart from radMouseNow you get the angle you would have to rotate about, to get the image from the start-position to the now-position. But, when we would rotate about this angle, the image would rotate like crazy. Why is it like that? - There are several miliseconds between "start" and "now" where the image is already rotating. So: when you're "now" rotating, you don't beginn at radMouseStart but at radImageNow - radImageStart + radMouseStart.
\o/ all problems are solved \o/
The code:
var imgObj = new Kinetic.Image
({
image: YourImg,
x: YourSize.x,
y: YourSize.y,
draggable: true
});
imgObj.rotPoint = {x: 500, y: 500};
imgObj.setOffset
(
imgObj.rotPoint.x - imgObj.getAbsolutePosition().x,
imgObj.rotPoint.y - imgObj.getAbsolutePosition().y
);
imgObj.move(imgObj.getOffsetX(),imgObj.getOffsetY());
var o = {x: imgObj.rotPoint.x, y: imgObj.rotPoint.y}; // shortcut
imgObj.on('mousedown', function()
{
posMouseStart = stage.getMousePosition();
radMouseStart = Math.atan2(-(posMouseStart.y - o.y), posMouseStart.x - o.x);
radImageStart = this.getRotation();
});
imgObj.setDragBoundFunc(function(pos)
{
var posMouseNow = stage.getMousePosition();
var radMouseNow = Math.atan2(-(posMouseNow.y - o.y), posMouseNow.x - o.x);
var radImageNow = this.getRotation();
var radMouseDiff = -(radMouseNow - radMouseStart);
this.rotate(radImageStart + radMouseDiff - radImageNow);
return {x: this.getAbsolutePosition().x, y: this.getAbsolutePosition().y};
});
Upvotes: 1
Reputation: 105015
You can move an image around a fixed rotation point using some trigonometry
Calculate the angle of the mouse position relative to the rotation point using Math.atan2:
var dx=mouseX-rotationPointX;
var dy=mouseY-rotationPointY;
var radianAngle=Math.atan2(dy,dx);
Move the image around the rotationPoint using Math.cos and Math.sin:
var x=rotationPointX+radius*Math.cos(radianAngle)-imgWidth/2;
var y=rotationPointY+radius*Math.sin(radianAngle)-imgHeight/2;
image.setPosition(x,y);
Here's working example code:
<!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.4.min.js"></script>
<style>
body{ padding:15px; }
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:300px;
height:300px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
var rx=150;
var ry=150;
var radius=75;
var image;;
var imgWidth=50;
var imgHeight=50;
var rotationPoint=new Kinetic.Circle({
x:rx,
y:ry,
radius:10,
fill:"green"
});
layer.add(rotationPoint);
$(stage.getContent()).on('mousemove', function (event) {
// get the current mouse position on the stage
var pos=stage.getMousePosition();
var mouseX=parseInt(pos.x);
var mouseY=parseInt(pos.y);
// calculate the mouse angle relative
// to the rotation point [rx,ry]
var dx=mouseX-rx;
var dy=mouseY-ry;
var radianAngle=Math.atan2(dy,dx);
// "normalize" the angle so it always is in a proper range (0-2*PI)
radianAngle=(radianAngle+Math.PI*2)%(Math.PI*2);
// calculate the new image x,y
// based on the angle
var x=rx+radius*Math.cos(radianAngle)-imgWidth/2;
var y=ry+radius*Math.sin(radianAngle)-imgHeight/2;
image.setPosition(x,y);
layer.draw();
});
var img=new Image();
img.onload=function(){
image=new Kinetic.Image({
image:img,
x:0,
y:0,
width:imgWidth,
height:imgHeight,
});
layer.add(image);
layer.draw();
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house-icon.png";
}); // end $(function(){});
</script>
</head>
<body>
<p>Move mouse to rotate image around</p>
<p>the green dot which is located at</p>
<p>the rotation point</p>
<div id="container"></div>
</body>
</html>
Upvotes: 0