<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="cropper.js"></script>
<script src="script.js"></script>
</head>
<body>
<h2>Cropper</h2>
<div id="cropper">
<img id="srcImage" src="http://placehold.it/350x350"/>
</div>
<button id="doCrop">Crop</button><br>
<button id="reset">Reset</button>
</body>
</html>
var cropCanvas, cropContext, cropping;
document.addEventListener('DOMContentLoaded', function(){
var crop = new cropper('cropper', 3/4);
document.getElementById('reset').addEventListener('click', function() {
crop.reset();
});
document.getElementById('doCrop').addEventListener('click', function() {
crop.getState();
});
});
/* Styles go here */
#srcImage {display: none;}
#doCrop {clear: both;}
#cropper {height: 350px;}
var cropper = function(container, aspect) {
this.container = document.getElementById(container);
if (aspect) this.aspect = aspect;
this.init();
return this;
};
cropper.prototype = {
cropperContext: null,
cropping: null,
state: {
x: 0,
y: 0,
x2: 100,
y2: 100,
ref: {
x: 0,
y: 0,
x2: 100,
y2: 100
}
},
action: null,
init: function() {
this.img = this.container.getElementsByTagName('img')[0];
this.container.style.position = 'relative';
this.img.style.display = 'none';
this.imageCanvas = document.createElement('canvas');
this.imageCanvas.width = this.img.width;
this.imageCanvas.height = this.img.height;
this.imageCanvas.style.position = 'absolute';
this.imageCanvas.style.zIndex = 0;
this.imageContext = this.imageCanvas.getContext("2d");
this.imageContext.drawImage(this.img, 0, 0);
this.container.appendChild(this.imageCanvas);
this.cropperCanvas = document.createElement('canvas');
this.cropperCanvas.width = this.img.width;
this.cropperCanvas.height = this.img.height;
this.cropperCanvas.style.position = 'absolute';
this.cropperCanvas.style.zIndex = 1;
this.cropperContext = this.cropperCanvas.getContext("2d");
this.container.appendChild(this.cropperCanvas);
this.cropRect(this.cropperContext, this.state.x, this.state.y, this.state.x2, this.state.y2);
var self = this;
this.cropperCanvas.addEventListener('mousedown', function(evt) {
var e = self.getMousePos(self.cropperCanvas, evt);
self.cropping = true;
self.state.ref.x = e.x;
self.state.ref.y = e.y;
if (Math.abs(self.state.x - e.x) <= 15 && Math.abs(self.state.y - e.y) <= 15) {
self.action = 'ul';
self.cropperCanvas.style.cursor = 'nw-resize';
} else if (Math.abs(self.state.x2 - e.x) <= 15 && Math.abs(self.state.y - e.y) <= 15) {
self.action = 'ur';
self.cropperCanvas.style.cursor = 'ne-resize';
} else if (Math.abs(self.state.x2 - e.x) <= 15 && Math.abs(self.state.y2 - e.y) <= 15) {
self.action = 'lr';
self.cropperCanvas.style.cursor = 'se-resize';
} else if (Math.abs(self.state.x - e.x) <= 15 && Math.abs(self.state.y2 - e.y) <= 15) {
self.action = 'll';
self.cropperCanvas.style.cursor = 'sw-resize';
} else {
self.action = 'drag';
self.cropperCanvas.style.cursor = 'move';
}
});
this.cropperCanvas.addEventListener('mouseup', function(e) {
self.cropping = false;
self.cropperCanvas.style.cursor = 'default';
});
this.cropperCanvas.addEventListener('mousemove', function(evt) {
var e = self.getMousePos(self.cropperCanvas, evt);
if (self.cropping) {
if (self.action == 'ul') {
var newX = self.state.x + (e.x - self.state.ref.x);
var newY = self.aspect ? self.state.y2 - (self.state.x2 - newX) / self.aspect : self.state.y + (e.y - self.state.ref.y);
self.cropRect(self.cropperContext, newX, newY, self.state.x2, self.state.y2);
self.state.x = newX;
self.state.y = newY;
self.state.ref.x = e.x;
self.state.ref.y = e.y;
} else if (self.action == 'ur') {
var newX = self.state.x2 + (e.x - self.state.ref.x);
var newY = self.aspect ? self.state.y2 - (newX - self.state.x) / self.aspect : self.state.y + (e.y - self.state.ref.y);
self.cropRect(self.cropperContext, self.state.x, newY, newX, self.state.y2);
self.state.x2 = newX;
self.state.y = newY;
self.state.ref.x = e.x;
self.state.ref.y = e.y;
} else if (self.action == 'lr') {
var newX = self.state.x2 + (e.x - self.state.ref.x);
var newY = self.aspect ? self.state.y + (newX - self.state.x) / self.aspect : self.state.y2 + (e.y - self.state.ref.y);
self.cropRect(self.cropperContext, self.state.x, self.state.y, newX, newY);
self.state.x2 = newX;
self.state.y2 = newY;
self.state.ref.x = e.x;
self.state.ref.y = e.y;
} else if (self.action == 'll') {
var newX = self.state.x + (e.x - self.state.ref.x);
var newY = self.aspect ? self.state.y + (self.state.x2 - newX) / self.aspect : self.state.y2 + (e.y - self.state.ref.y);
self.cropRect(self.cropperContext, newX, self.state.y, self.state.x2, newY);
self.state.x = newX;
self.state.y2 = newY;
self.state.ref.x = e.x;
self.state.ref.y = e.y;
} else {
// drag
var newX = self.state.x + (e.x - self.state.ref.x);
var newY = self.state.y + (e.y - self.state.ref.y);
var newX2 = newX + (self.state.x2 - self.state.x);
var newY2 = newY + (self.state.y2 - self.state.y);
self.cropRect(self.cropperContext, newX, newY, newX2, newY2);
self.state.x = newX;
self.state.y = newY;
self.state.ref.x = e.x;
self.state.ref.y = e.y;
self.state.x2 = newX2;
self.state.y2 = newY2;
}
}
});
},
getMousePos: function(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
},
cropRect: function(ctx, x, y, x2, y2) {
ctx.clearRect(0, 0, this.img.width, this.img.height);
ctx.beginPath();
ctx.lineWidth = "3";
ctx.strokeStyle = "red";
var w = Math.abs(x - x2);
var h = Math.abs(y - y2);
ctx.rect(x, y, w, h);
ctx.stroke();
},
getState: function() {
var state = {
x: this.state.x,
y: this.state.y,
x2: this.state.x2,
y2: this.state.y2,
w: this.state.x2 - this.state.x,
h: this.state.y2 - this.state.y
};
this.imageContext.clearRect(0, 0, this.img.width, this.img.height);
this.cropperContext.clearRect(0, 0, this.img.width, this.img.height);
this.imageContext.drawImage(this.img, state.x, state.y, state.w, state.h,
0, 0, state.w, state.h);
return state;
},
reset: function() {
this.imageContext.clearRect(0, 0, this.img.width, this.img.height);
this.init();
}
};