Skip to content

Instantly share code, notes, and snippets.

@nccharles
Created November 1, 2021 17:14
Show Gist options
  • Save nccharles/cfce199d024085bedc01a15fa7d90bb6 to your computer and use it in GitHub Desktop.
Save nccharles/cfce199d024085bedc01a15fa7d90bb6 to your computer and use it in GitHub Desktop.
Crop image
<h1>Cropping an image using HTML5 Canvas</h1>
<div class="wrapper">
<canvas id='c1'></canvas><!--
--><canvas id='c2'></canvas>
<p id="output"></p>
<p>Move the cropping bars to enclose the desired area of interest (left canvas).<br>Then you may drag to reposition the cropped image (right canvas).</p>
</div>
var proportion = .8; // you may change the proportion for the cropped image.
var theImage = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg";
/*
original image:
----------------------------
| | |
| |sy |
|_____|____________ |
| sx | | |
| | | |
| | | sh |
| | | |
| |___________| |
| sw |
| |
| |
|__________________________|
cropped image:
----------------------------
| | |
| |y |
|_____|_________ |
| x | | |
| | | h |
| |________| |
| w |
| |
| |
|__________________________|
ctx.drawImage(img,sx,sy,sw,sh,x,y,w,h)
*/
var output = document.getElementById("output");
var c1 = document.getElementById("c1");
var ctx1 = c1.getContext("2d");
var c2 = document.getElementById("c2");
var ctx2 = c2.getContext("2d");
var cw = c1.width = c2.width = 400,
cx = cw / 2;
var ch = c1.height = c2.height = 400,
cy = ch / 2;
var isDragging1 = false;
var isDragging2 = false;
var sy = 20;
var sx = 130;
var sw = 200;
var sh = 200;
var r = 4;
var mousePos1 = {
x: 0,
y: 0
};
var mousePos2 = {
x: 0,
y: 0
};
var o = { // cropping bars
"sx": {
color: "white",
x: 0,
y: sy,
w: cw,
h: r,
bool: false,
},
"sy": {
color: "yellow",
x: sx,
y: 0,
w: r,
h: ch,
bool: false,
},
"sw": {
color: "orange",
x: 0,
y: sy + sh,
w: cw,
h: r,
bool: false,
},
"sh": {
color: "red",
x: sx + sw,
y: 0,
w: r,
h: ch,
bool: false,
}
}
function drawGuides(o) {
for (k in o) {
ctx1.fillStyle = o[k].color;
ctx1.beginPath();
ctx1.fillRect(o[k].x, o[k].y, o[k].w, o[k].h);
}
}
function Imgo(o, d) { // an object defining the cropped image
var imgo = {
sx: o.sy.x,
sy: o.sx.y,
sw: o.sh.x - o.sy.x,
sh: o.sw.y - o.sx.y,
w: ~~((o.sh.x - o.sy.x) * proportion),
h: ~~((o.sw.y - o.sx.y) * proportion),
x: d.x,
y: d.y
}
return imgo;
}
var d = {
x: ~~(cx - sw * proportion / 2),
y: ~~(cy - sh * proportion / 2)
}
function Output(Imgo, output) {
output.innerHTML = "ctx.drawImage(img," + imgo.sx + "," + imgo.sy + "," + imgo.sw + "," + imgo.sh + "," + imgo.x + "," + imgo.y + "," + imgo.w + "," + imgo.h + ")";
}
function drawCroppedImage(imgo) {
ctx2.drawImage(img, imgo.sx, imgo.sy, imgo.sw, imgo.sh, imgo.x, imgo.y, imgo.w, imgo.h);
}
function outlineImage(imgo) {
ctx2.beginPath();
ctx2.rect(imgo.x, imgo.y, imgo.w, imgo.h);
}
function cursorStyleC1() {
c1.style.cursor = "default";
for (k in o) { //o[k].bool = false;
ctx1.beginPath();
ctx1.rect(o[k].x - 10, o[k].y - 10, o[k].w + 20, o[k].h + 20);
if (ctx1.isPointInPath(mousePos1.x, mousePos1.y)) {
if (k == "sx" || k == "sw") {
c1.style.cursor = "row-resize";
} else {
c1.style.cursor = "col-resize";
}
break;
} else {
c1.style.cursor = "default";
}
}
}
function cursorStyleC2() {
c2.style.cursor = "default";
outlineImage(imgo);
if (ctx2.isPointInPath(mousePos2.x, mousePos2.y)) {
c2.style.cursor = "move";
} else {
c2.style.cursor = "default";
}
}
drawGuides(o);
var imgo = Imgo(o, d); // an object defining the cropped image
Output(Imgo, output); // text: "drawImage(img,130,10,200,220,150,145,100,110)";
var img = new Image();
img.src = theImage;
img.onload = function() {
c1.style.backgroundImage = "url("+theImage+")";
drawCroppedImage(imgo);
}
// mousedown ***************************
c1.addEventListener('mousedown', function(evt) {
isDragging1 = true;
mousePos1 = oMousePos(c1, evt);
for (k in o) {
ctx1.beginPath();
ctx1.rect(o[k].x - 10, o[k].y - 10, o[k].w + 20, o[k].h + 20);
if (ctx1.isPointInPath(mousePos1.x, mousePos1.y)) {
o[k].bool = true;
if (k == "sx" || k == "sw") {
o[k].y = mousePos1.y;
} else {
o[k].x = mousePos1.x;
}
break;
} else {
o[k].bool = false;
}
}
Output(Imgo, output);
}, false);
c2.addEventListener('mousedown', function(evt) {
mousePos2 = oMousePos(c2, evt);
outlineImage(imgo)
if (ctx2.isPointInPath(mousePos2.x, mousePos2.y)) {
isDragging2 = true;
deltaX = mousePos2.x - imgo.x;
deltaY = mousePos2.y - imgo.y;
Output(Imgo, output);
}
}, false);
// mousemove ***************************
c1.addEventListener('mousemove', function(evt) {
mousePos1 = oMousePos(c1, evt); //console.log(mousePos)
cursorStyleC1();
if (isDragging1 == true) {
ctx1.clearRect(0, 0, cw, ch);
for (k in o) {
if (o[k].bool) {
if (k == "sx" || k == "sw") {
o[k].y = mousePos1.y;
} else {
o[k].x = mousePos1.x;
}
break;
}
}
drawGuides(o);
ctx2.clearRect(0, 0, cw, ch);
imgo = Imgo(o, d);
drawCroppedImage(imgo);
Output(Imgo, output);
}
}, false);
c2.addEventListener('mousemove', function(evt) {
mousePos2 = oMousePos(c2, evt);
if (isDragging2 == true) {
ctx2.clearRect(0, 0, cw, ch);
d.x = mousePos2.x - deltaX;
d.y = mousePos2.y - deltaY;
imgo = Imgo(o, d);
drawCroppedImage(imgo);
Output(Imgo, output);
}
cursorStyleC2();
}, false);
// mouseup ***************************
c1.addEventListener('mouseup', function(evt) {
isDragging1 = false;
for (k in o) {
o[k].bool = false;
}
}, false);
c2.addEventListener('mouseup', function(evt) {
isDragging2 = false;
}, false);
// mouseout ***************************
c1.addEventListener('mouseout', function(evt) {
isDragging1 = false;
for (k in o) {
o[k].bool = false;
}
}, false);
c2.addEventListener('mouseout', function(evt) {
isDragging2 = false;
}, false);
function oMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top)
}
}
body {
margin: 0;
padding: 0;
background: #eee;
font-family: Courier, monospace;
font-size: 16px;
background-color: #000;
color: white;
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.wrapper {
display: block;
margin: 0 auto;
padding: 0;
width: 844px;
}
canvas {
margin: 10px;
padding: 0;
border: 1px solid #333;
display: inline-block;
}
p {
text-align: left;
margin-left: 10px;
}
h1 {
font-size: 1.5em;
font-family: Arial, Helvetica, sans-serif;
padding: 1em 0 0;
}
/*#c1 {
background-image: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg)
}*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment