I have five anchors and the middle one is for rotating. It works well with the original size. But after resizing, when I click it, the anchor fly away from the image. I did set the position to new ones. http://jsfiddle.net/W9X8n/1/
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
//var rotateAnchor = group.get('.rotateAnchor')[0];
var rotateAnchorNew = group.get('.rotateAnchorNew')[0];
var image = group.get('Image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
var imageWidth = image.getWidth();
var imageHeight = image.getHeight();
// update anchor positions
switch (activeAnchor.getName()) {
//case 'rotateAnchor':
// break;
case 'rotateAnchorNew':
break;
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
topRight.setX(anchorX);
bottomLeft.setY(anchorY);
break;
case 'bottomLeft':
topLeft.setX(anchorX);
bottomRight.setY(anchorY);
break;
}
if (topRight.getX() < topLeft.getX() + minImgSize) {
topRight.setX(topLeft.getX() + minImgSize);
}
if (bottomRight.getX() < topLeft.getX() + minImgSize) {
bottomRight.setX(topLeft.getX() + minImgSize);
}
if (bottomRight.getY() < topLeft.getY() + minImgSize) {
bottomRight.setY(topLeft.getY() + minImgSize);
}
if (bottomLeft.getY() < topLeft.getY() + minImgSize) {
bottomLeft.setY(topLeft.getY() + minImgSize);
}
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
image.setPosition({ x: topLeft.getPosition().x, y: (topLeft.getPosition().y) });
image.setWidth(width);
image.setHeight(height);
rotateAnchorNew.setX(width / 2 + topLeft.getX());
rotateAnchorNew.setY(height / 2 + topLeft.getY());
}
KineticJS automatically adjusts the left & top position of an object based on the offset.
This is frustrating because this same offset must be used to set the rotation point.
As a result, it is difficult to coordinate the [x,y,offsetX,offsetY] of your image with the [x,y] of the anchors--especially when the image has been both resized and rotated.
If either your image or your anchors unexpectedly "jump", you are experiencing the side-effects of using KineticJS offsets.
Here's one way to deal with this difficulty:
Declare the rotation point as the centerpoint of the image.
Use this centerpoint-rotationpoint to position both the image and the anchors.
When any anchor is activated, use this centerpoint to reset the image's x,y & offsets.
When any anchor is activated, reposition all anchors relative to this centerpoint.
By making all transformations relative to the rotation point, you eliminate the need to coordinate the image's x,y with each anchor's x,y.
Here's annotated code and a Demo: http://jsfiddle.net/m1erickson/TWAj3/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;background:lightgray}
#container{
border:solid 1px green;
margin-top: 10px;
width:400px;
height:400px;
}
</style>
<script>
$(function(){
// create the stage and layer
var stage = new Kinetic.Stage({
container: 'container',
width: 400,
height: 400
});
var layer = new Kinetic.Layer();
stage.add(layer);
// create an anchor used to drag-move the image
var spotXY=new Kinetic.Circle({
x:0,y:0,radius:10,
fill: 'blue',stroke:'black',
draggable: true
});
spotXY.on("dragmove",function(){
setNode(image,this.x(),this.y(),image.width(),image.height(),image.rotation());
});
layer.add(spotXY);
// create an anchor used to drag-resize the image
var resizer=new Kinetic.Circle({
x:0,y:0,radius:10,
fill: 'red',stroke:'black',
draggable: true
});
resizer.on("dragmove",function(){
var dx=this.x()-spotXY.x();
var dy=this.y()-spotXY.y();
var w=Math.sqrt(dx*dx+dy*dy)*2;
var h=w*hRatio;
setNode(image,spotXY.x(),spotXY.y(),w,h,image.rotation());
});
layer.add(resizer);
// create an anchor used to drag-rotate the image
var rotator=new Kinetic.Circle({
x:0,y:0,radius:10,
fill: 'gold',stroke:'black',
draggable: true
});
rotator.on("dragmove",function(){
var dx=this.x()-spotXY.x();
var dy=this.y()-spotXY.y();
var angle=Math.atan2(dy,dx)*180/Math.PI;
setNode(image,spotXY.x(),spotXY.y(),image.width(),image.height(),angle);
});
layer.add(rotator);
// always resize the image proportionally to it's original aspect ratio
// this variable is used to keep that proportion
var hRatio;
// load the image
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/facesSmall.png";
function start(){
// save the images original aspect ratio
hRatio=img.height/img.width;
// start
loadK(150,150);
};
function loadK(x,y){
// create an image element
image=new Kinetic.Image({
x:0,y:0,width:10,height:10,
image:img,
rotation:0,
});
layer.add(image);
// setNode will reset all image and anchor properties when needed
// This sets the initial properties at startup
setNode(image,x,y,img.width,img.height,45);
// make sure the anchors are on top of the z-index
spotXY.moveToTop();
rotator.moveToTop();
resizer.moveToTop();
layer.draw();
}
// Reset all image and anchor properties relative to the rotation point (x,y)
// This is the key to simplifying KineticJS transformations with anchors
function setNode(node,x,y,w,h,angle){
// reset all size and position properties on the image
node.width(w);
node.height(h);
node.x(x);
node.y(y);
node.offsetX(w/2);
node.offsetY(h/2);
node.rotation(angle);
// postion the move anchor
spotXY.position({x:x,y:y});
// calculate the radian angle of the image
var rAngle=angle*Math.PI/180;
// position the rotation anchor
var rotationRadius=(w/2+resizer.radius()*2);
var xx=x+rotationRadius*Math.cos(rAngle);
var yy=y+rotationRadius*Math.sin(rAngle);
rotator.position({x:xx,y:yy});
// position the resizing anchor
var xx=x+w/2*Math.cos(rAngle);
var yy=y+w/2*Math.sin(rAngle);
resizer.position({x:xx,y:yy});
layer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drag the dots to transform the image<br>Blue=Move, Red=Resize, Gold=Rotate<br>Image will always resize by maintaining aspect ratio</h4>
<div id="container"></div>
</body>
</html>