Gire âncora não fixa na imagem após o redimensionamento
Pergunta
Eu tenho cinco âncoras e o do meio é a de rotação.Ele funciona bem com o tamanho original.Mas depois de redimensionar, quando eu clicar nele, o âncora voar para longe da imagem.Eu fiz definir a posição novos. 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());
}
Solução
KineticJS ajusta automaticamente a esquerda e de cima a posição de um objeto com base no deslocamento.
Isso é frustrante, porque este mesmo deslocamento deve ser usado para definir o ponto de rotação.
Como resultado, é difícil de coordenadas [x,y,offsetX,offsetY] de sua imagem com a [x,y] das âncoras--especialmente quando a imagem foi redimensionada e rodado.
Se a sua imagem ou a sua âncoras inesperadamente "salto", que estão enfrentando os efeitos colaterais do uso de KineticJS deslocamentos.
Aqui está uma maneira de lidar com essa dificuldade:
Declarar o ponto de rotação como o ponto central da imagem.
Use esta centralidade-rotationpoint para a posição da imagem e as âncoras.
Quando qualquer âncora é ativado, use esta centralidade para repor a imagem de x,a y & deslocamentos.
Quando qualquer âncora é ativado, reposicionar todas as âncoras em relação a este ponto central.
Fazendo todas as transformações em relação ao ponto de rotação, você elimina a necessidade de coordenar a imagem de x,y de cada âncora de x,y.
Aqui está o código anotado e uma Demonstração: 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>