我已经在使用jQuery
名为 j 的插件,Crop
但最近我发现KinectJs
它确实为我解决了很多问题。然后我偶然发现了这个例子:
http://www.html5canvastutorials.com/labs/html5-canvas-drag-and-drop-resize-and-invert-images/
我决定根据KinectJs
上面的例子编写我自己的裁剪矩形。
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 cropper = group.get('.cropper')[0];
var leftMask = group.getParent().get('.leftMask')[0];
var rightMask = group.getParent().get('.rightMask')[0];
var topMask = group.getParent().get('.topMask')[0];
var bottomMask = group.getParent().get('.bottomMask')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
updateLeftMaskWidth(leftMask,activeAnchor);
updateTopMaskHeight(topMask,cropper,activeAnchor);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
updateRightMaskWidthAndPos(rightMask,activeAnchor);
updateTopMaskHeight(topMask,cropper,activeAnchor);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
updateRightMaskWidthAndPos(rightMask,activeAnchor);
updateBottomMaskHeightAndPos(bottomMask,cropper,activeAnchor);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
updateLeftMaskWidth(leftMask,activeAnchor);
updateBottomMaskHeightAndPos(bottomMask,cropper,activeAnchor);
break;
}
cropper.setPosition(topLeft.getPosition().x,topLeft.getPosition().y);
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if(width && height) {
cropper.setSize(width, height);
}
}
function updateLeftMaskWidth(mask,leftAnchor) {
mask.setWidth(leftAnchor.getAbsolutePosition().x - 100);
}
function updateRightMaskWidthAndPos(mask,rightAnchor) {
mask.setAbsolutePosition(rightAnchor.getAbsolutePosition().x,mask.getAbsolutePosition().y);
mask.setWidth(213 - (rightAnchor.getAbsolutePosition().x - 100));
}
function updateTopMaskHeight(mask,cropper,topAnchor) {
mask.setAbsolutePosition(topAnchor.getAbsolutePosition().x,mask.getAbsolutePosition().y);
mask.setHeight(topAnchor.getAbsolutePosition().y - 110);
mask.setWidth(cropper.getWidth());
}
function updateBottomMaskHeightAndPos(mask,cropper,bottomAnchor) {
mask.setAbsolutePosition(bottomAnchor.getAbsolutePosition().x, bottomAnchor.getAbsolutePosition().y);
mask.setHeight(236 - (bottomAnchor.getAbsolutePosition().y - 110));
mask.setWidth(cropper.getWidth());
}
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 1,
radius: 5,
name: name,
draggable: true,
dragBoundFunc: function(pos) {
var newX = pos.x;
var newY = pos.y;
var image = this.getParent().getParent().get('.image')[0];
var cropper = this.getParent();
// Bound horizontally
if(newX < 100) {
newX = 100;
}
else if(newX > image.getWidth() + 100 - cropper.getWidth()) {
newX = image.getWidth() + 100 - cropper.getWidth();
}
if(newY < 110) {
newY = 110;
}
else if(newY > image.getHeight() + 110 - cropper.getHeight()) {
newY = image.getHeight() + 110 - cropper.getHeight();
}
return {
x: newX,
y: newY
}
}
});
anchor.on('dragmove', function() {
update(this);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function() {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(2);
layer.draw();
});
anchor.on('mouseout', function() {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
function initStage(img) {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 400
});
var imageGroup = new Kinetic.Group({
x: 100,
y: 110
});
var leftMaskGroup = new Kinetic.Group({
x: 100,
y: 110
});
var rightMaskGroup = new Kinetic.Group({
x: 270,
y: 110
});
var topMaskGroup = new Kinetic.Group({
x: 169.9,
y: 110
});
var bottomMaskGroup = new Kinetic.Group({
x: 169.9,
y: 150+138
});
var cropperGroup = new Kinetic.Group({
x: 170,
y: 150,
draggable: true,
dragBoundFunc: function(pos) {
var newX = pos.x;
var newY = pos.y;
var image = this.getParent().get('.image')[0];
var cropper = this.get('.cropper')[0];
// Bound horizontally
if(newX < 100) {
newX = 100;
}
else if(newX > image.getWidth() + 100 - cropper.getWidth()) {
newX = image.getWidth() + 100 - cropper.getWidth();
}
// Bound vertically
if(newY < 110) {
newY = 110;
}
else if(newY > image.getHeight() + 110 - cropper.getHeight()) {
newY = image.getHeight() + 110 - cropper.getHeight();
}
return {
x: newX,
y: newY
}
}
});
var layer = new Kinetic.Layer();
/*
* go ahead and add the groups
* to the layer and the layer to the
* stage so that the groups have knowledge
* of its layer and stage
*/
layer.add(imageGroup);
layer.add(leftMaskGroup);
layer.add(rightMaskGroup);
layer.add(topMaskGroup);
layer.add(bottomMaskGroup);
layer.add(cropperGroup);
stage.add(layer);
// cropping rectangle
var cropperRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 100,
height: 138,
stroke: 'black',
name: 'cropper',
strokeWidth: 1
});
cropperGroup.add(cropperRect);
addAnchor(cropperGroup, 0, 0, 'topLeft');
addAnchor(cropperGroup, 100, 0, 'topRight');
addAnchor(cropperGroup, 100, 138, 'bottomRight');
addAnchor(cropperGroup, 0, 138, 'bottomLeft');
cropperGroup.on('dragstart', function() {
this.moveToTop();
});
cropperGroup.on('dragmove', function() {
var layer = this.getLayer();
var topLeft = this.get('.topLeft')[0];
var bottomLeft = this.get('.bottomLeft')[0];
var topRight = this.get('.topRight')[0];
var leftMask = this.getParent().get('.leftMask')[0];
var rightMask = this.getParent().get('.rightMask')[0];
var topMask = this.getParent().get('.topMask')[0];
var bottomMask = this.getParent().get('.bottomMask')[0];
updateLeftMaskWidth(leftMask,topLeft);
updateRightMaskWidthAndPos(rightMask,topRight);
updateTopMaskHeight(topMask,this.get('.cropper')[0],topLeft);
updateBottomMaskHeightAndPos(bottomMask,this.get('.cropper')[0],bottomLeft);
layer.draw();
});
// left mask
var leftMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 70,
height: 236,
fill: 'black',
name: 'leftMask',
strokeWidth: 0,
opacity: 0.5
});
leftMaskGroup.add(leftMaskRect);
// right mask
var rightMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 213-170,
height: 236,
fill: 'black',
name: 'rightMask',
strokeWidth: 0,
opacity: 0.5
});
rightMaskGroup.add(rightMaskRect);
// top mask
var topMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 100.2,
height: 150-110,
fill: 'black',
name: 'topMask',
strokeWidth: 0,
opacity: 0.5
});
topMaskGroup.add(topMaskRect);
// bottom mask
var bottomMaskRect = new Kinetic.Rect({
x: 0,
y: 0,
width: 100.2,
height: 236-138-(150-110),
fill: 'black',
name: 'bottomMask',
strokeWidth: 0,
opacity: 0.5
});
bottomMaskGroup.add(bottomMaskRect);
// image
var srcImg = new Kinetic.Image({
x: 0,
y: 0,
image: img,
name: 'image'
});
imageGroup.add(srcImg);
stage.draw();
}
var img = new Image();
img.onload = function() {
initStage(this);
}
img.src = 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg';
它工作得几乎完美。问题是,当您使用圆形锚点调整大小时,经过几次尝试(只是给它一些镜头),当您尝试拖动整个矩形时,它允许您将其拖出边界!
从我的调试来看,这似乎是库的问题,但如果 sb. 在我的代码中看到问题或看到优化它的方法,请分享您的想法。
我的努力的结果可以在这里看到: