2

I have to draw 3 images on the canvas and need to rotate 2 of the images.

The images are like 1. circular with a vertical straight line 2. just an horizontal line 3. Big circular image

I need to rotate the 1st 2 images in the center of the canvas.

var canvas = document.getElementById('NewImage');
    var context = canvas.getContext('2d');
    context.canvas.width  = window.innerWidth;
    context.canvas.height = window.innerHeight*0.7;
    var imageObj = new Image();
    var imageObj2 = new Image();
    var imageObj3 = new Image();

    imageObj.onload = function() {
        context.save();    
        context.translate(imageObj.width/2,imageObj.height/2);
        context.rotate(-10*Math.PI/180);
        //context.translate(-imageObj.width/2,-imageObj.height/2);
        context.drawImage(imageObj,-(imageObj.width/2),-(imageObj.height/2),context.canvas.width,context.canvas.height*0.85);
        context.restore();
        context.save();
        context.globalCompositeOperation="source-over";
        context.translate(imageObj2.width/2,imageObj2.height/2);
        context.rotate(-10*Math.PI/180);
        context.translate(-imageObj2.width/2,-imageObj2.height/2);
        context.drawImage(imageObj2, x, y,context.canvas.width,6);
        context.restore();
        //context.rotate(10*Math.PI/180);
        context.drawImage(imageObj3, 0, 0,context.canvas.width,context.canvas.height*0.9);

    };
    imageObj.src  = 'canvas/inner_circle_blackline_vertical.png';
    imageObj2.src = 'canvas/horizontal.png';
    imageObj3.src = 'canvas/outer_circle.png';

When i try to rotate, the images are not rotating in center. when 1st 2 images rotates it has to look like "X" symbol.

How will i rotate in center of the canvas.

Thanks:)

Beginner
  • 1,414
  • 2
  • 21
  • 41

2 Answers2

2

As designed, your imageObj2 and imageObj3 will never load.

Here is a generic image loader that will load all your images and store them in an array called imgs[].

When all your images have fully loaded, the render() function will be called. That’s where you start drawing.

// This is an image loader 
// When render() is called, all your images are fully loaded
var imgURLs = [
    "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png",
    "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png",
    "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png"];
var imgs=[];
var imgCount=0;

pre_load();

function pre_load(){

    for(var i=0;i<imgURLs.length;i++){

        var img=new Image();
        imgs.push(img);
        img.onload=function(){        

            if(++imgCount>=imgs.length){ 
                // images are now fully loaded
                render(); 
            }

        }
        img.src=imgURLs[i];
    }
}

In render(), you just draw your images.

Since the same action (rotating an image) is done repeatedly, you can create a helper function to do the rotated drawing. Here the helper function is drawImageAtAngle.

// draw the rotated lines on the canvas
function render(){

    var x=canvas.width/2;
    var y=canvas.height/2;

    drawImageAtAngle(imgs[0],x,y,-45);
    drawImageAtAngle(imgs[2],x,y,45);
    drawImageAtAngle(imgs[1],x,y,0);
}

Here the helper function that rotates a supplied image to a supplied angle:

function drawImageAtAngle(image,X,Y,degrees){
    var radians=degrees*Math.PI/180;
    var halfWidth=image.width/2;
    var halfHeight=image.height/2;
    ctx.beginPath();
    ctx.save();
    ctx.translate(X,Y);
    ctx.rotate(radians);
    ctx.drawImage(image,-halfWidth,-halfHeight);
    ctx.restore();
}

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/ZShWW/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:10px;}
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

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

    // This is an image loader 
    // When render() is called, all your images are fully loaded
    var imgURLs = [
        "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png",
        "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png",
        "https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png"];
    var imgs=[];
    var imgCount=0;

    pre_load();

    function pre_load(){

        for(var i=0;i<imgURLs.length;i++){

            var img=new Image();
            imgs.push(img);
            img.onload=function(){        

                if(++imgCount>=imgs.length){ 
                    // images are now fully loaded
                    render(); 
                }

            }
            img.src=imgURLs[i];
        }
    }


    // draw the rotated lines on the canvas
    function render(){

        var x=canvas.width/2;
        var y=canvas.height/2;

        drawImageAtAngle(imgs[0],x,y,-45);
        drawImageAtAngle(imgs[2],x,y,45);
        drawImageAtAngle(imgs[1],x,y,0);
    }


    function drawImageAtAngle(image,X,Y,degrees){
        var radians=degrees*Math.PI/180;
        var halfWidth=image.width/2;
        var halfHeight=image.height/2;
        ctx.beginPath();
        ctx.save();
        ctx.translate(X,Y);
        ctx.rotate(radians);
        ctx.drawImage(image,-halfWidth,-halfHeight);
        ctx.restore();
    }





}); // end $(function(){});
</script>

</head>

<body>
    <p>This is the line image</p>
    <img src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/line.png">
    <p>The line image rotated at center of canvas</p>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
markE
  • 102,905
  • 11
  • 164
  • 176
  • thanks for the answer. i want some thing like this i have a circular image, now i have to draw one vertical line and 1 horizontal line at the center(angle between horizontal and vertical should be 90 degree), this i am able to do. but after that i have to rotate them by certain degree. and keep both of them in center and angle between them should be 90 only. how can i do that? Thanks:) – Beginner Jul 05 '13 at 18:11
  • The drawImageAtAngle function in my answer will allow you to specify drawing your image at any angle. To have a 90 degree angle between your horizontal and vertical images, just be sure that the degrees you specify are different by 90. For example: drawImageAtAngle(yourHorizImage,150,150,120) plus drawImageAtAngle(yourVertImage,150,150,210) will rotate your images 90 degrees apart (210 degrees-120 degrees). And if you specify the same x,y for your horiz and vert images, they will be drawn with the same center--in your case the x,y would be x=canvas.width/2 y=canvas.height/2. – markE Jul 05 '13 at 18:31
  • Very comprehensive answer. – Vincent Ramdhanie Jul 05 '13 at 19:19
  • @markE great answer sir. thanks:) but i am using it to mobile phone. i am setting the canvas width and height to window.innerWidth and window.innerHeight. and when i run my app, the lines are displaying at 90 degree. but the images are being sliced. they are not displaying fully.. can you please help sir???. Thanks:) – Beginner Jul 06 '13 at 06:07
  • Sliced--Do you mean the phone screen is too small to fully display the images? I don't understand :/ – markE Jul 06 '13 at 06:28
  • yea.. i am using nexus phone for testing. i am not able to scale the images before drawing. – Beginner Jul 06 '13 at 06:54
  • No problem: drawImage can scale your images while drawing: drawImage(image,0,0,image.width,image.height,-halfWidth/2,-halfHeight/2,halfWidth,halfHeight) This will scale the images to half-size and then draw them. – markE Jul 06 '13 at 07:02
  • @markE sir images looks to be pixalted after rotating. how will i remove? – Beginner Jul 08 '13 at 13:54
  • Yes, images will naturally do that when rotated. The reason is that every image pixel must be interpolated to a new position when an image rotates. It's especially visible on the outer edges of a rotated image (jaggies). The solution for you might be to use canvas lines and arcs instead of images. That way you can let the browser do anti-aliasing on your rotated lines/arcs and they will appear less pixelated. – markE Jul 08 '13 at 14:17
  • is their a way i can hide the rotated image and display some other image, which is not pixelated?? – Beginner Jul 09 '13 at 09:26
  • I guess if you had an image for each angle of rotation you could display just the appropriate image...seems like a lot of work to prepare all those images. Unless there is something unique about the line/circle images, I would instead use canvas's great drawing ability to create the effect ;) – markE Jul 09 '13 at 14:23
  • @markE sir can u suggest some help for this http://stackoverflow.com/questions/17554168/drawing-images-on-3-layer-canvas-and-saving. i am able to disply only one canvas at a time.. – Beginner Jul 09 '13 at 17:51
  • Sure, glad to help! Check out my answer to your question at that link – markE Jul 09 '13 at 18:13
0

To find the center of the canvas you have to use the dimensions of the canvas. In your code you are using the dimensions of the image. That is, this line:

  context.translate(imageObj.width/2,imageObj.height/2);

should probably be:

  context.translate(canvas.width/2,canvas.height/2);

That moves you to the center of the canvas. The rotation then occurs around that center. You are then drawing the image centered on the origin. That part looks correct.

You will then reverse the rotation and then the translation.

Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
  • i tried that but didnt work. i have a circular image, now i have to draw one vertical line and 1 horizontal line at the center(angle between horizontal and vertical should be 90 degree), this i am able to do. but after that i have to rotate them by certain degree. and keep both of them in center and angle between them should be 90 only. how can i do that? Thanks:) – Beginner Jul 05 '13 at 17:33