Reputation: 659
I am trying to implement a rotate
function for my photo editor. I'm relatively new working with HTML5
elements, especially canvas
elements.
Now, the image will rotate after clicking the button but it doesn't do it while maintaining the aspect ratio. To be specific as possible, I have included two images below: one before the rotation button was clicked and one after that.
As you can see, image does indeed rotate but it will crop majority of the image. Am I missing something? Any help would be much appreciated.
Here's what I've tried so far with results shown above:
function rotateImage(degrees, image) {
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");
if(degrees == 90 || degrees == 270) {
canvas.width = image.height;
canvas.height = image.width;
} else {
canvas.width = image.width;
canvas.height = image.height;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(degrees == 90 || degrees == 270) {
ctx.translate(image.height/2,image.width/2);
} else {
ctx.translate(image.width/2,image.height/2);
}
ctx.rotate(degrees * Math.PI / 180);
ctx.drawImage(image, -image.width / 2 , -image.height / 2);
var dataURL = canvas.toDataURL();
$("#image").attr('src', dataURL);
}
document.getElementById("rotate").addEventListener("click", function() {
var el = this;
var data = el.getAttribute('data-value');
var angleInDegrees = 0;
if(data == 90) {
angleInDegrees += 90 % 360;
} else {
if(angleInDegrees == 0) {
angleInDegrees = 270;
} else {
angleInDegrees -= 90;
}
}
// rotate the image based on degree value
rotateImage(angleInDegrees, document.getElementById("canvas"));
});
EDIT:
Now, it does indeed rotate the image while maintaining the aspect ratio but only do it once. If rotate button is clicked again, it crops about 20% of the original image size. Few more pictures to demonstrate:
BEFORE ROTATION
AFTER ROTATION BUTTON WAS CLICKED ONCE
AFTER ROTATION BUTTON WAS CLICKED AGAIN
Modified function
function rotateImage(degrees, image) {
var canvas = document.createElement("canvas"),
ctx = canvas.getContext("2d");
if(degrees == 90 || degrees == 270) {
canvas.width = image.height;
canvas.height = image.width;
} else {
canvas.width = image.width;
canvas.height = image.height;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
if(degrees == 90 || degrees == 270) {
ctx.translate(image.height/2,image.width/2);
} else {
ctx.translate(image.width/2,image.height/2);
}
ctx.rotate(degrees * Math.PI / 180);
ctx.drawImage(image, -image.width / 2 , -image.height / 2);
ctx.restore();
var dataURL = canvas.toDataURL();
image.setAttribute('src', dataURL);
}
Upvotes: 2
Views: 1089
Reputation: 33024
I've made a few changes to your code.
if(data == "90")
instead of if(data == 90)
because it's a stringvar canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d");
let cw = canvas.width = image.width;
let ch = canvas.height = image.height;
ctx.drawImage(image, 0 , 0);
function rotateImage(degrees, image) {
if(degrees == 90 || degrees == 270) {
cw = image.height;
ch = image.width;
} else {
cw = image.width;
ch = image.height;
}
ctx.clearRect(0, 0, cw, ch);
ctx.save()
ctx.translate(cw/2,ch/2);
ctx.rotate(degrees * Math.PI / 180);
ctx.drawImage(image, -image.width / 2 , -image.height / 2);
ctx.restore();
var dataURL = canvas.toDataURL();
image.setAttribute('src', dataURL);
}
rotate.addEventListener("click", function() {
var el = this;
var data = el.dataset.value; console.log(data)
var angleInDegrees = 0;
if(data == "90") {
angleInDegrees += 90 % 360;
} else {
if(angleInDegrees == 0) {
angleInDegrees = 270;
} else {
angleInDegrees -= 90;
}
}
// rotate the image based on degree value
rotateImage(angleInDegrees, image);
});
Upvotes: 2