Hendrian
Hendrian

Reputation: 23

JavaScript - Rotate canvas image, corners are clipped off

I'm trying to rotate an image inside a HTML canvas. The rotating does work, but however, each single rotation time, the corners of the image are cut/clipped off. This is wrong because the whole uploaded image should be intact after rotating.

Some important details:

So the problem here is that each time I want to rotate the image 45 degrees, the corners of the image inside the HTML canvas are clipped/cutted off. Obvious this is not correct since the whole image should be rotated. I can't figure out what I did wrong so maybe someone can help me futher?

https://jsfiddle.net/d5zurxq2/

<label>Image File:</label><br/>
<input type="file" id="imageLoader" name="imageLoader"/>
<canvas id="imageCanvas" width=250 height=250></canvas>
<br /><br /><br />
<button type="button" id="rotateLeft">Rotate 45 degrees left</button>


#imageCanvas {
  width: 350px;
  height: 250px;
  background-color: rgba(158, 167, 184, 0.2)
}

var imageLoader = document.getElementById('imageLoader');
    imageLoader.addEventListener('change', handleImage, false);


var canvas  = document.getElementById('imageCanvas');
var ctx     = canvas.getContext("2d");


function handleImage(e){
  var reader            = new FileReader();
  reader.onload         = function(e) {
      var preview       = document.createElement('img');
      preview.onload    = function()
      {
          canvas.width  = preview.width;
          canvas.height = preview.height;
          canvas.getContext('2d').drawImage(preview, 0, 0);
      };

      preview.src = reader.result;
    };

   reader.readAsDataURL(e.target.files[0]);     
}



document.getElementById('rotateLeft').addEventListener('click', rotateImage, 
false);

function rotateImage() {
  var w     = ctx.canvas.width;
  var h     = ctx.canvas.height;
  var ww    = w / 2;
  var hh    = h / 2;

  ctx.save();
  ctx.globalCompositeOperation = "copy";
  ctx.translate(ww, hh);
  ctx.rotate((Math.PI / 180) * 45);
  ctx.drawImage(canvas, -canvas.width/2, -canvas.height/2);
  ctx.restore();
}

Upvotes: 2

Views: 1500

Answers (2)

Eese
Eese

Reputation: 1

You can do that and more with the Canvate library.

http://www.sakuracode.com/canvate

You can load all the images as you want and trate them as individual clips. You can set the point of rotation too. In this case in the middle.

You need something like that?

function rotateImage() {
        clip.rotation = 45;
        clip.fitInto(canvas.width, canvas.height);
    }

https://codepen.io/EiseiKashi/pen/aGjbWK

For any doubt please let me know!

Upvotes: 0

kockburn
kockburn

Reputation: 17616

These two statements are contradictory.

The canvas width and height should be exact the same as the width & height of the uploaded image.

The canvas itself should maintain its dimensions and should not be rotated, only the image in it should be rotated.

Increase the size of your canvas. A larger canvas is required if you rotate your image 45 degrees.

For now, you set the canvas size to the image size. However, rotating your image doesn't rotate your canvas, reason why the edges are cut off.

Here is a canvas (in blue), with an image (in yellow) exactly the same size but drawn at a 45 degree angle. The edges of the image that stick out, are not drawn... because they're not on the canvas.

enter image description here

Increase the canvas size to make up for the image rotation. I'd recommend calculating the diagonal length of your image and set that as the width and height of your canvas, this way no matter how you rotate it, it'll fit.

Something like this:

  let diagonalLength = Math.sqrt(
    Math.pow(preview.width,2)+Math.pow(preview.height,2)    
  );
  canvas.width  = diagonalLength;
  canvas.height = diagonalLength;

Upvotes: 3

Related Questions