I'm using a resize with KineticJS that i've found and finetuned it to fit my needs(http://www.html5canvastutorials.com/labs/html5-canvas-drag-and-drop-resize-and-invert-images/)
One of those needs is that my users can reset the position of their image to a specific X and Y position and make the image fitting to the drawingBox(Which is defined by the script. It's the box that's center/center and is the part being cutout on save). However; When i resize the image in the top left corner the X and Y become a negative number. So if i want my user to be able to reset their image to, let's say, 0, 0. The 0, 0 line is off after they've resized with the topLeft anchor.
Is there a way to workout to 0, 0 line via an other way. Or perhaps use the group or layer the image it's in as a baseline?
The stage init(It draws 4 rectangles around the border to match the drawbox. Everything will be overlayed except for a box in the center/center which will be the cutout off the image on save.
function initStage(image) {
stage = new Kinetic.Stage({
container: 'container',
width: workspaceWidth,
height: workspaceHeight
});
//Get the top, bottom, left and right square sized. used for X/y positioning and the creation of the ovelray
var top_bottom_sides = (workspaceHeight-drawboxHeight)/2;
var left_right_sides = (workspaceWidth-drawboxWidth)/2;
imageGroupX = left_right_sides;
imageGroupY = Math.ceil(top_bottom_sides);
imgGroup = new Kinetic.Group({
/*x: (workspaceWidth/2)-(image.width/2),
y: (workspaceHeight/2)-(image.height/2),*/
x: imageGroupX,
y: imageGroupY,
draggable: true,
dragOnTop: false
})
layer = new Kinetic.Layer();
//add the imgGroup to the layer and the layer to the stage.
imageImg = new Kinetic.Image({
/*x: left_right_sides-imgGroup.getX(),
y: Math.ceil(top_bottom_sides)-imgGroup.getY(),*/
x: 0,
y: 0,
image: image,
width: image.width,
height: image.height,
name: 'image',
});
imgGroup.add(imageImg);
layer.add(imgGroup);
addAnchor(imgGroup, 0, 0, 'topLeft');
addAnchor(imgGroup, image.width, 0, 'topRight');
addAnchor(imgGroup, image.width, image.height, 'bottomRight');
addAnchor(imgGroup, 0, image.height, 'bottomLeft');
//Create 4 rectangles and place them around the borders to create an overlay which matches the drawing box
//Ceil the height to avoid 0.5 pixel overlap on some dimensions
rect1 = new Kinetic.Rect({ //top
x: 0,
y: 0,
width: workspaceWidth,
height: Math.ceil(top_bottom_sides),
fill: '#000000',
opacity: 1,
listening: false
});
//Floor the height to not have a 0.5 pixel overlap on some dimensions
rect2 = new Kinetic.Rect({ // bottom
x: 0,
y: Math.ceil(workspaceHeight-top_bottom_sides),
width: workspaceWidth,
height: Math.floor(top_bottom_sides),
fill: '#000000',
opacity: 1,
listening: false
});
rect3 = new Kinetic.Rect({ //right
x: rect1.getWidth()-left_right_sides,
y: rect1.getX()+rect1.getHeight(),
width: left_right_sides,
height: drawboxHeight,
fill: '#000000',
opacity: 1,
listening: false
});
rect4 = new Kinetic.Rect({ //left
x: rect1.getX(),
y: rect1.getX()+rect1.getHeight(),
width: left_right_sides,
height: drawboxHeight,
fill: '#000000',
opacity: 1,
listening: false
});
layer.add(rect1);
layer.add(rect2);
layer.add(rect3);
layer.add(rect4);
layer.on('mouseover', function() {
rect1.setOpacity(0.5);
rect2.setOpacity(0.5);
rect3.setOpacity(0.5);
rect4.setOpacity(0.5);
layer.draw();
});
layer.on('mouseout', function() {
rect1.setOpacity(1);
rect2.setOpacity(1);
rect3.setOpacity(1);
rect4.setOpacity(1);
layer.draw();
});
stage.add(layer);
stage.draw();
fitImage();
}
My update which does the anchor-dragging resize:
function update(activeAnchor, optionalX, optionalY) {
//var group = activeAnchor.getParent();
var group = imgGroup;
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 image = group.get('.image')[0];
if (optionalX && optionalY) {
var anchorX = optionalX;
var anchorY = optionalY;
} else {
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
}
var activeHandleName = activeAnchor.getName();
// update anchor positions
switch (activeHandleName) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
if (jQuery('#keep_ratio:checked').val() != undefined) {
// Calculate new dimensions. Height is simply the dy of the handles.
// Width is increased/decreased by a factor of how much the height changed.
newHeight = bottomLeft.getY() - topLeft.getY();
newWidth = image.getWidth() * newHeight / image.getHeight();
// Move the image to adjust for the new dimensions.
// The position calculation changes depending on where it is anchored.
// ie. When dragging on the right, it is anchored to the top left,
// when dragging on the left, it is anchored to the top right.
if(activeHandleName === "topRight" || activeHandleName === "bottomRight") {
image.setPosition(topLeft.getX(), topLeft.getY());
} else if(activeHandleName === "topLeft" || activeHandleName === "bottomLeft") {
image.setPosition(topRight.getX() - newWidth, topRight.getY());
}
} else {
var newWidth = topRight.getX() - topLeft.getX();
var newHeight = bottomLeft.getY() - topLeft.getY();
if(activeHandleName === "topRight" || activeHandleName === "bottomRight") {
image.setPosition(topLeft.getX(), topLeft.getY());
} else if(activeHandleName === "topLeft" || activeHandleName === "bottomLeft") {
image.setPosition(topRight.getX() - newWidth, topRight.getY());
}
}
imageX = image.getX();
imageY = image.getY();
// Update handle positions to reflect new image dimensions
topLeft.setPosition(imageX, imageY);
topRight.setPosition(imageX + newWidth, imageY);
bottomRight.setPosition(imageX + newWidth, imageY + newHeight);
bottomLeft.setPosition(imageX, imageY + newHeight);
var width = newWidth;
var height = newHeight;
if(width && height) {
width = Math.round(width);
height = Math.round(height);
image.setSize(width, height);
}
}
The fitImage function and the setSizeManually:
function fitImage() {
if (imageImg) {
var widthDifference = (imageImg.getWidth() > drawboxWidth) ? imageImg.getWidth()-drawboxWidth : drawboxWidth-imageImg.getWidth();
var heightDifference = (imageImg.getHeight() > drawboxHeight) ? imageImg.getHeight()-drawboxHeight : drawboxHeight-imageImg.getHeight();
var ratio = imageImg.getWidth()/imageImg.getHeight();
if (widthDifference > heightDifference) {
//Fit the image horizontally and scale it vertically
var newHeight = Math.ceil(drawboxWidth / ratio);
var newWidth = drawboxWidth+1;
} else {
//Fit the image vertically and scale it horizontally
var newWidth = Math.round(drawboxHeight * ratio);
var newHeight = drawboxHeight+1;
}
imageImg.setWidth(newWidth);
imageImg.setHeight(newHeight);
setSizeManually(newWidth, newHeight);
}
}
function setSizeManually(width, height, isSlider) {
var stage = imgGroup.getStage();
update(imgGroup.get('.bottomRight')[0], width, height, isSlider);
stage.draw();
}