Click here to Skip to main content
14,742,749 members
Articles » Web Development » HTML / CSS » HTML
Article
Posted 13 Nov 2017

Stats

14.2K views
3 bookmarked

Rotate a rectangular image in an HTML5 canvas

Rate me:
Please Sign up or sign in to vote.
3.86/5 (5 votes)
14 Nov 2017CPOL
How to rotate 90 degrees a rectangular image (such as a camera photo) using HTML5

Introduction

I found myself building a website to upload photos. Sometimes the photos needed some rotation. The user could cancel the upload, rotate them locally and restart, but I was trying to find a way to rotate these images, that are usually rectangular, in the same page. 

Background

If you need an introduction about HTML5 canvas rotation feature, you can take a look to the following link: http://www.html5canvastutorials.com/advanced/html5-canvas-transform-rotate-tutorial/

Using the code

I start builing a basic html document with an image myImage and a canvas myCanvas elements:

<!DOCTYPE html>
<html>
<body>

<p>Image:</p>
<img id="myImage" width="220" height="277" src="myimage.jpg" alt="myImage">

<p>Canvas:</p>
<canvas id="myCanvas" width="240" height="297" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script> ... </script>
</body>
</html>

In the script, I have the following:

<script>

window.onload = function() {
    var c = document.getElementById("myCanvas");
    var img = document.getElementById("myImage");
  
    //canvas must be squared and take the bigger size width or height
    var cnvsSize;
    if (img.width > img.height)
          {
              cnvsSize = img.width;
              isHorizontal = true;        
          }
          else
            {
              cnvsSize = img.height;
              isHorizontal = false;
            }
        c.width=cnvsSize;
        c.height= cnvsSize;
        
        var ctx = c.getContext("2d");
        ctx.clearRect(0,0,c.width,c.height);
                
        //go to the center of the canvas and rotate
        ctx.translate(c.width/2,c.height/2);
        ctx.rotate(90*Math.PI/180);
        
        //default x and y to draw
        var Y = -cnvsSize/2;
        var X = -cnvsSize/2;
        
        //calculate the x and y for the image to be drawn
        if (isHorizontal){
        Y = (- img.height)/2;
        }
        else{
        X = (- img.width)/2;
        }
                
        ctx.drawImage(img,X,Y);
        
        //a temporary squared image
        var imgSquared = new Image();
   
        //take the data of the squared image
        imgSquared.src = c.toDataURL("image/jpg");     
              
        
        imgSquared.onload = function() {
        
          //resize the canvas to the oposite to the original image
          c.width= img.height;
          c.height= img.width;           
           
           //source is my squared image
           if (isHorizontal)
           {
             var sourceX = (cnvsSize - c.width)/2;
             var sourceY = 0;
            }
            else 
            {
             var sourceX = 0;
             var sourceY = (cnvsSize - c.height)/2;           
            }
              
            var sourceWidth = c.width;
            var sourceHeight = c.height;
   
            //destination is canvas resized
            var destX = 0;
            var destY = 0;
            var destWidth = c.width;
            var destHeight = c.height;
        
            ctx.clearRect(0,0,c.width,c.height);

            ctx.drawImage(imgSquared,sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
            
            imgSquared = null;
        };
}
</script>

So, after retreiving MyCanvas and MyImage from the document, I resize the canvas to be squared taking the bigger size of the image (width or height).

Later, I retrieved the context and clear the whole rectangle (in fact an square) of the canvas.
Next, I translate the (0,0) to the center of the canvas and rotate it.

Next, I calculate where the image should be drawn. By default, it should be minus half of the size of the canvas (considering with are starting from the center of the canvas).
Considering if the image is horizontal or vertical, this coordinates could be smaller to only minus half of the size of the image.
Once calculate the coordinates, the image is drawn.

Next, I create a temporary image to save the square image from the canvas. 
In the onload event of this image, the canvas is resize to the dimension expected for the rotated image (width to height and height to width of the original image).
In order to draw the temporary image in the resized canvas, I had to calculate the x, y, width and height of the image source that should be drawn in the x, y, width and height of the destination canvas.
According to the dimension of the image (horizontal or vertical), there is a margin that need to be left from the temporary image. For that I compare the original canvas size with the current size (cnvsSize - c.height)/2.

Finally, the context clear the rectangle of the canvas and the image is drawn again...happyly rotated!!.

Points of Interest

The canvas look powerful, only requires some patient to understand how it works.

History

Keep a running update of any changes or improvements you've made here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Silvia Campo
Canada Canada
No Biography provided

Comments and Discussions

 
GeneralMy vote of 4 Pin
DrABELL14-Nov-17 5:52
professionalDrABELL14-Nov-17 5:52 
Useful article. I've implemented similar functionality in my web app using CSS3 transform/transition feature (sample: http://alexanderbell.us/Quiz/)

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.