HTML5 image crop tool
I have prepared new great HTML5 tool for you (with tutorial). I have made ‘Crop tool’ in html5 (canvas). Now we can crop images at client side too. Now we don`t need to send data (with crop coordinates) back to server as we did in our previous article: ‘Image Crop Plugin – using Jcrop’.
Here are our demo and downloadable package:
Live Demo
download in package
Ok, download the source files and lets start coding !
Step 1. HTML
Small code with canvas element and blank image (for future cropped image)
index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 image crop tool | Script Tutorials</title>
<link href="css/main.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="js/script.js"></script>
</head>
<body>
<header>
<h2>HTML5 image crop tool</h2>
<a href="http://www.script-tutorials.com/html5-image-crop-tool/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
</header>
<div class="container">
<div class="contr">
<button onclick="getResults()">Crop</button>
</div>
<canvas id="panel" width="779" height="519"></canvas>
<div id="results">
<h2>Please make selection for cropping and click 'Crop' button.</h2>
<img id="crop_result" />
</div>
</div>
</body>
</html>
Step 2. CSS
css/main.css
We are going to skip of publishing styles today again (no need).
Step 3. HTML5 JS
js/script.js
// variables
var canvas, ctx;
var image;
var iMouseX, iMouseY = 1;
var theSelection;
// define Selection constructor
function Selection(x, y, w, h){
this.x = x; // initial positions
this.y = y;
this.w = w; // and size
this.h = h;
this.px = x; // extra variables to dragging calculations
this.py = y;
this.csize = 6; // resize cubes size
this.csizeh = 10; // resize cubes size (on hover)
this.bHow = [false, false, false, false]; // hover statuses
this.iCSize = [this.csize, this.csize, this.csize, this.csize]; // resize cubes sizes
this.bDrag = [false, false, false, false]; // drag statuses
this.bDragAll = false; // drag whole selection
}
// define Selection draw method
Selection.prototype.draw = function(){
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.strokeRect(this.x, this.y, this.w, this.h);
// draw part of original image
if (this.w > 0 && this.h > 0) {
ctx.drawImage(image, this.x, this.y, this.w, this.h, this.x, this.y, this.w, this.h);
}
// draw resize cubes
ctx.fillStyle = '#fff';
ctx.fillRect(this.x - this.iCSize[0], this.y - this.iCSize[0], this.iCSize[0] * 2, this.iCSize[0] * 2);
ctx.fillRect(this.x + this.w - this.iCSize[1], this.y - this.iCSize[1], this.iCSize[1] * 2, this.iCSize[1] * 2);
ctx.fillRect(this.x + this.w - this.iCSize[2], this.y + this.h - this.iCSize[2], this.iCSize[2] * 2, this.iCSize[2] * 2);
ctx.fillRect(this.x - this.iCSize[3], this.y + this.h - this.iCSize[3], this.iCSize[3] * 2, this.iCSize[3] * 2);
}
function drawScene() { // main drawScene function
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // clear canvas
// draw source image
ctx.drawImage(image, 0, 0, ctx.canvas.width, ctx.canvas.height);
// and make it darker
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// draw selection
theSelection.draw();
}
$(function(){
// loading source image
image = new Image();
image.onload = function () {
}
image.src = 'images/image.jpg';
// creating canvas and context objects
canvas = document.getElementById('panel');
ctx = canvas.getContext('2d');
// create initial selection
theSelection = new Selection(200, 200, 200, 200);
$('#panel').mousemove(function(e) { // binding mouse move event
var canvasOffset = $(canvas).offset();
iMouseX = Math.floor(e.pageX - canvasOffset.left);
iMouseY = Math.floor(e.pageY - canvasOffset.top);
// in case of drag of whole selector
if (theSelection.bDragAll) {
theSelection.x = iMouseX - theSelection.px;
theSelection.y = iMouseY - theSelection.py;
}
for (i = 0; i < 4; i++) {
theSelection.bHow[i] = false;
theSelection.iCSize[i] = theSelection.csize;
}
// hovering over resize cubes
if (iMouseX > theSelection.x - theSelection.csizeh && iMouseX < theSelection.x + theSelection.csizeh &&
iMouseY > theSelection.y - theSelection.csizeh && iMouseY < theSelection.y + theSelection.csizeh) {
theSelection.bHow[0] = true;
theSelection.iCSize[0] = theSelection.csizeh;
}
if (iMouseX > theSelection.x + theSelection.w-theSelection.csizeh && iMouseX < theSelection.x + theSelection.w + theSelection.csizeh &&
iMouseY > theSelection.y - theSelection.csizeh && iMouseY < theSelection.y + theSelection.csizeh) {
theSelection.bHow[1] = true;
theSelection.iCSize[1] = theSelection.csizeh;
}
if (iMouseX > theSelection.x + theSelection.w-theSelection.csizeh && iMouseX < theSelection.x + theSelection.w + theSelection.csizeh &&
iMouseY > theSelection.y + theSelection.h-theSelection.csizeh && iMouseY < theSelection.y + theSelection.h + theSelection.csizeh) {
theSelection.bHow[2] = true;
theSelection.iCSize[2] = theSelection.csizeh;
}
if (iMouseX > theSelection.x - theSelection.csizeh && iMouseX < theSelection.x + theSelection.csizeh &&
iMouseY > theSelection.y + theSelection.h-theSelection.csizeh && iMouseY < theSelection.y + theSelection.h + theSelection.csizeh) {
theSelection.bHow[3] = true;
theSelection.iCSize[3] = theSelection.csizeh;
}
// in case of dragging of resize cubes
var iFW, iFH;
if (theSelection.bDrag[0]) {
var iFX = iMouseX - theSelection.px;
var iFY = iMouseY - theSelection.py;
iFW = theSelection.w + theSelection.x - iFX;
iFH = theSelection.h + theSelection.y - iFY;
}
if (theSelection.bDrag[1]) {
var iFX = theSelection.x;
var iFY = iMouseY - theSelection.py;
iFW = iMouseX - theSelection.px - iFX;
iFH = theSelection.h + theSelection.y - iFY;
}
if (theSelection.bDrag[2]) {
var iFX = theSelection.x;
var iFY = theSelection.y;
iFW = iMouseX - theSelection.px - iFX;
iFH = iMouseY - theSelection.py - iFY;
}
if (theSelection.bDrag[3]) {
var iFX = iMouseX - theSelection.px;
var iFY = theSelection.y;
iFW = theSelection.w + theSelection.x - iFX;
iFH = iMouseY - theSelection.py - iFY;
}
if (iFW > theSelection.csizeh * 2 && iFH > theSelection.csizeh * 2) {
theSelection.w = iFW;
theSelection.h = iFH;
theSelection.x = iFX;
theSelection.y = iFY;
}
drawScene();
});
$('#panel').mousedown(function(e) { // binding mousedown event
var canvasOffset = $(canvas).offset();
iMouseX = Math.floor(e.pageX - canvasOffset.left);
iMouseY = Math.floor(e.pageY - canvasOffset.top);
theSelection.px = iMouseX - theSelection.x;
theSelection.py = iMouseY - theSelection.y;
if (theSelection.bHow[0]) {
theSelection.px = iMouseX - theSelection.x;
theSelection.py = iMouseY - theSelection.y;
}
if (theSelection.bHow[1]) {
theSelection.px = iMouseX - theSelection.x - theSelection.w;
theSelection.py = iMouseY - theSelection.y;
}
if (theSelection.bHow[2]) {
theSelection.px = iMouseX - theSelection.x - theSelection.w;
theSelection.py = iMouseY - theSelection.y - theSelection.h;
}
if (theSelection.bHow[3]) {
theSelection.px = iMouseX - theSelection.x;
theSelection.py = iMouseY - theSelection.y - theSelection.h;
}
if (iMouseX > theSelection.x + theSelection.csizeh && iMouseX < theSelection.x+theSelection.w - theSelection.csizeh &&
iMouseY > theSelection.y + theSelection.csizeh && iMouseY < theSelection.y+theSelection.h - theSelection.csizeh) {
theSelection.bDragAll = true;
}
for (i = 0; i < 4; i++) {
if (theSelection.bHow[i]) {
theSelection.bDrag[i] = true;
}
}
});
$('#panel').mouseup(function(e) { // binding mouseup event
theSelection.bDragAll = false;
for (i = 0; i < 4; i++) {
theSelection.bDrag[i] = false;
}
theSelection.px = 0;
theSelection.py = 0;
});
drawScene();
});
function getResults() {
var temp_ctx, temp_canvas;
temp_canvas = document.createElement('canvas');
temp_ctx = temp_canvas.getContext('2d');
temp_canvas.width = theSelection.w;
temp_canvas.height = theSelection.h;
temp_ctx.drawImage(image, theSelection.x, theSelection.y, theSelection.w, theSelection.h, 0, 0, theSelection.w, theSelection.h);
var vData = temp_canvas.toDataURL();
$('#crop_result').attr('src', vData);
$('#results h2').text('Well done, we have prepared our cropped image, now you can save it if you wish');
}
Most of code is already commented. So I will hope that you will understand all this code. If not – you always can ask me any questions.
Live Demo
download in package
Conclusion
Welcome back to read something new and interesting about HTML5. Good luck in your projects.

very usefull.thanks admin
Thank you so need it for
This is great. Thanks! I am trying to add a resize function to this and I’m not able to get it working
I tried:
var currentScale = 1;
var minScale = .2
var maxScale =3 ;
var scaleIncrement = .1
document.onkeydown = function(e){
e = e?e:window.event;
console.log(e.keyCode + “down”);
switch (e.keyCode){
case 109:
//-
currentScale-=scaleIncrement;
if (currentScalemaxScale){
currentScale = maxScale;
}
}
ctx.scale(currentScale, currentScale)
}
It does resize the image but its layering it overtop the original and then I can’t select the crop tool. Essentially I would like to be able to resize and then crop. Please would you mind showing me what I’m doing wrong?
Thanks
Hello Drew,
As the first, please add ; at the end of each line. And, if you have any online version of your work, I can try to work (in order to understand what are you trying to achieve). It will be more easy for me to understand it and to give you advice.
ok well last post but as you are moderating this I am reposting because it doesn’t seem to be taking my full function… but I would assume you get the idea….sorry again for multiple posts..
I used to be very happy to search out this web-site.I needed to thanks in your time for this glorious read!! I undoubtedly having fun with each little bit of it and I’ve you bookmarked to take a look at new stuff you blog post.