Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    New Coder
    Join Date
    Jan 2010
    Location
    Wisconsin
    Posts
    24
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Canvas Not cooperating at all.

    I just cant wrap my mind around canvas. As far as I can tell theres no logical reason as to why the code would not work. Could someone take a look at it and possibly figure out whats wrong?

    I'm trying to intialize and draw a canvas with a simple image. I have the functions in a custom namespace in javascript. I am also using Jquery

    Code:
    var birdr = new Image();
    var birdl = new Image();
    
    $(document).ready(function(){
    
    if(Modernizr.canvas){
       var c = document.createElement('canvas');
    
       LK.animLoad();
    
       document.getElementById('backg-canvas').appendChild(c);
    
       $('canvas').attr({'width':'500','height':'500','id':'canvas'}); 
    
       var context = LK.returnCanvas();
       context.drawImage(birdl, 400,487,10,10);
    }
    
    
    });
    
    var LK = {
    	birdx: 400, //unused (lets just get it to draw the image first :\)
    	birdy: 487, //unused
    	animLoad: function(){
    		birdl.src = "images/bird2.png";
    		birdr.src = "images/bird.png";
    		//alert(birdl);
    		//alert(birdr);
    	},
    	returnCanvas: function(ca){
    		var b_canvas = LK.getCanvas();
    		var b_context = b_canvas.getContext('2d');
    		return b_context;
    	},
    	getCanvas: function(){
    		var a_canvas = document.getElementById('canvas');
    		//alert(a_canvas);
    		return a_canvas;
    	}
    
    }
    Any help would be greatly appreciate thanks.

    Btw safari web inspector indicates the canvas is getting properly created and appended to the container div. So that all works fine.

  • #2
    Regular Coder
    Join Date
    Jul 2010
    Posts
    185
    Thanks
    3
    Thanked 42 Times in 42 Posts
    Your code is kind of convoluted for what you are trying to do. I assume you are starting to write some kind of framework for a bigger project.

    context.drawImage(birdl, 400,487,10,10);
    The size of your canvas is 500x500. The result of the drawImage() function you are calling will take the image (birdl) scale it to a size of 10x10 and place it at 400,487. So you have a 10px by 10px image in the bottom right of the canvas.
    If this is what you want, make sure that the "backg-canvas" element is the correct size.

    Also, your images may not be loaded by the time you try to draw them to the canvas. You may want to try something like this (no JQuery for clarity):
    Code:
    // Create and resize the canvas
    canvas = document.createElement("canvas");
    canvas.width = 500;
    canvas.height = 500;
    
    // Append the canvas to the "backg-canvas" element
    document.getElementById("backg-canvas").appendChild(canvas);
    
    // Get the context
    context = canvas.getContext("2d");
    
    // Create the birdL image
    birdL = new Image();
    birdL.src = "bird.png";
    
    // When the image is loaded ... do the drawing
    birdL.onload = function() {
        // Draw the image (unscaled) at the top left of the canvas
        context.drawImage(birdL,0,0);
    }
    For more canvas stuff see:
    https://developer.mozilla.org/en/Canvas_tutorial
    http://canvashtml5.com

    I hope this is of some use to you.

  • #3
    New Coder
    Join Date
    Jan 2010
    Location
    Wisconsin
    Posts
    24
    Thanks
    2
    Thanked 0 Times in 0 Posts

    HTML5 Javascript Animation

    Quote Originally Posted by disastro View Post
    Your code is kind of convoluted for what you are trying to do. I assume you are starting to write some kind of framework for a bigger project.



    The size of your canvas is 500x500. The result of the drawImage() function you are calling will take the image (birdl) scale it to a size of 10x10 and place it at 400,487. So you have a 10px by 10px image in the bottom right of the canvas.
    If this is what you want, make sure that the "backg-canvas" element is the correct size.

    Also, your images may not be loaded by the time you try to draw them to the canvas. You may want to try something like this (no JQuery for clarity):
    Code:
    // Create and resize the canvas
    canvas = document.createElement("canvas");
    canvas.width = 500;
    canvas.height = 500;
    
    // Append the canvas to the "backg-canvas" element
    document.getElementById("backg-canvas").appendChild(canvas);
    
    // Get the context
    context = canvas.getContext("2d");
    
    // Create the birdL image
    birdL = new Image();
    birdL.src = "bird.png";
    
    // When the image is loaded ... do the drawing
    birdL.onload = function() {
        // Draw the image (unscaled) at the top left of the canvas
        context.drawImage(birdL,0,0);
    }
    For more canvas stuff see:
    https://developer.mozilla.org/en/Canvas_tutorial
    http://canvashtml5.com

    I hope this is of some use to you.
    Thanks, yes as with most things i post on the magical forums i somehow figure it out afterwards. It is a small part of a larger picture, i want to animate a specific image.

    Adding the onload allows me to draw the image at a later time for a different frame.

    Unfortunitely now its a question as to how to animate it. I do not believe i have the ability to figure this out at this time.

  • #4
    Regular Coder
    Join Date
    Jul 2010
    Posts
    185
    Thanks
    3
    Thanked 42 Times in 42 Posts
    Unfortunitely now its a question as to how to animate it
    Well, the best way is to keep everything seperate. Keep your animated object seperate from the canvas.

    In the following example, we will have one image (this means we don't need to wait for more than one image to load). The image is 64px by 32px. The region from 0,0 to 32,32 will contain frame 1 and the region from 32,0 to 64,32 will contain frame 2. We will use drawImage() to slice the appropriate frame from the image. We flip between the two frames by checking the value of a switch(toggle). Once we draw the frame, we will flip the toggle so the next frame will be rendered (rather than the same one over and over).

    Obviously this only works with a 2 frame animation.
    Code:
    // Our animated object
    Bird = new function() {
        // Set up animation frames
        this.image = new Image();
        // Our bird image will be 64px by 32px
        this.image.src = "bird.png"
        // Toggle for different frames
        this.state = false;
        return this;
    }
    
    function drawFrame(animObject,ctx) {
        // Clear our canvas
        ctx.clearRect(0,0,width,height);
        // If state==true then draw frame 1
        if(animObject.state) ctx.drawImage(animObject.image,0,0,32,32,0,0,32,32);
        // If state==false draw frame 2
        if(!animObject.state) ctx.drawImage(animObject.image,32,0,32,32,0,0,32,32);
        // Toggle the frame
        animObject.state = !animObject.state;
    }
    
    // The size of our canvas (needed by drawFrame and to resize canvas)
    width = 32;
    height = 32;
    
    // Set up the canvas. Assumes page has a canvas element called mycanvas
    canvas = document.getElementById("mycanvas");
    canvas.width = width;
    canvas.height = height;
    
    // Get the context
    context = canvas.getContext("2d");
    
    // Create a new animated bird
    myBird = new Bird();
    
    // Once the bird image is loaded ...
    myBird.image.onload = function() {
        // Draw a frame every 500 milliseconds
        setInterval("drawFrame(myBird,context)",500);
    }
    The image you use should look like this:
    Code:
    ---------------------------------
    |               |               |
    |       A       |       B       |
    |               |               |
    ---------------------------------
    Sorry, ASCII art is not my strong suit. "A" is your first frame and is 32x32, "B" is your second frame and is also 32x32.

    We draw a frame once every 500ms. When we draw frame 1, we set frame 2 to be the next frame. Likewise, when we draw frame 2, we set frame 1 to be next.

    If you wanted to pause the animation, just use clearInterval().

    Hopefully you can use this approach in your project.
    Last edited by disastro; 07-26-2010 at 08:52 PM. Reason: Typo

  • #5
    New Coder
    Join Date
    Jan 2010
    Location
    Wisconsin
    Posts
    24
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Thanks for the help! Actually im trying to animate an object without the use of frames. Moving the object within a specified amount of time.

    I have managed to animate 1 object, however it would be great if there were around 5 or so.

    Code:
    var birdr = new Image();
    var birdl = new Image();
    var birdar = new Array();
    var birdal = new Array();
    
    var y = 0;
    var x = 0;
    var interv = null;
    
    if(Modernizr.canvas){
       var c = document.createElement('canvas');
       LK.animLoad();
       document.getElementById('backg-canvas').appendChild(c);
       $('canvas').attr({'width':'500','height':'500','id':'canvas'}); 
       $('#enter').css({'bottom':'55em','position':'relative'});
       LK.init();
       setInterval(LK.randAnim, 1000);
    }
    
    var LK = {
    
    	delay: 500,
    	birdx: new Array(),
    	birdy: 487,
    	birdox: null,
    	birdoy: null,
    	origx: null,
    	origy: null,
    	origy2: null,
    	init: function(){
    	
    			var xrand = Math.floor(Math.random()*(450-50));
    			//alert(xrand);
    			LK.birdx = xrand;
    			//alert(LK.birdx[i]);
    
    	 		LK.draw();
    		
    	},
    	randAnim: function(ca){
    		
    		
    		var rand = Math.floor(Math.random()*2);
    		//rand = 1;
    		//alert(rand);
    		if(rand != 1)
    		{
    			return;
    		}
    		else
    		{
    			LK.animate();
    		}
    		
    	},
    	animate: function(ctx){
    		
    		var rand = Math.floor(Math.random()*2);
    		if(rand != 1)
    		{  // clear canvas
    			
    				LK.birdox = LK.birdx;
    				LK.birdoy = LK.birdy;
    				LK.origx = LK.birdox + 25;
    				//LK.origy = LK.birdoy - 25;
    				LK.origy = LK.birdoy - 6.25;
    				y = 0;
    				//$('#front').append(" |time| ");
    				interv = setInterval("LK.rmove()", 50);
    			
    		}
    		else
    		{
    				LK.birdox = LK.birdx;
    				LK.birdoy = LK.birdy;
    				LK.origx = LK.birdox - 25;
    				//LK.origy = LK.birdoy - 25;
    				LK.origy = LK.birdoy - 6.25;
    				y = 0;
    				//$('#front').append(" |time| ");
    				interv = setInterval("LK.lmove()", 50);
    		}
    		
    	},
    	animLoad: function(){
    	
    		birdl.src = "images/bird2.png";
    		birdr.src = "images/bird.png";
    		
    		//alert(birdl);
    		//alert(birdr);
    	},
    	returnCanvas: function(){
    		var b_canvas = LK.getCanvas();
    		var b_context = b_canvas.getContext('2d');
    		return b_context;
    	},
    	getCanvas: function(){
    		var a_canvas = document.getElementById('canvas');
    		//alert(a_canvas);
    		return a_canvas;
    	},
    	draw: function(){
    		var b_canvas = document.getElementById("canvas");
    		var b_context = b_canvas.getContext("2d");
    		
    			birdr.onload = function(){
    						b_context.drawImage(birdr, LK.birdx, LK.birdy,10,10);
    			}
    		
    		
    	},
    	rmove: function(i){
    	
    		if(LK.origx < 490)
    		{
    			var b = LK.returnCanvas();
    			b.clearRect(0,0,500,500);
    			if(x < 10)
    			{
    				x = x+1;
    				//$('#front').append(x + ' ');
    			}
    			
    			
    			if(LK.birdx < LK.origx)
    			{
    				LK.birdx = LK.birdx + 2.5;
    				
    				if(y == 0)
    				{
    					if(LK.birdy >  LK.origy)
    					{
    						LK.birdy = LK.birdy - 3.125;
    					}
    					else
    					{
    						//LK.birdy = LK.birdy - 5;
    						y = y+1;
    					}
    				}
    				else
    				{	
    					if(LK.birdy != LK.birdoy)
    					{
    						LK.birdy = LK.birdy + 3.125;
    						//alert(LK.birdy);
    					}
    				}
    				
    				b.drawImage(birdr, LK.birdx, LK.birdy,10,10);
    				//$('#front').append(LK.birdx + ' ');
    			}
    			else
    			{
    				y = 0;
    				x = 0;
    				//alert(LK.birdx);
    				//LK.birdy = LK.birdy + 6.25;
    				b.drawImage(birdr, LK.birdx, LK.birdy,10,10);
    				clearInterval(interv);
    			}
    			//end draw
    			
    		}
    		else
    		{
    			clearInterval(interv);
    			LK.origx = LK.birdox - 25;
    			//LK.origy = LK.birdoy - 25;
    			LK.origy = LK.birdoy - 6.25;
    			y = 0;
    			x = 0;
    			interv = setInterval("LK.lmove()", 50);
    		}
    			
    		
    	},
    	lmove: function(i){
    		if(LK.origx > 10)
    		{
    			var b = LK.returnCanvas();
    			b.clearRect(0,0,500,500);
    			if(x < 10)
    			{
    				x = x+1;
    				//$('#front').append(x + ' ');
    			}
    			
    			if(LK.birdx > LK.origx)
    			{
    				LK.birdx = LK.birdx - 2.5;
    				
    				if(y == 0)
    				{
    					if(LK.birdy >  LK.origy)
    					{
    						LK.birdy = LK.birdy - 3.125;
    					}
    					else
    					{
    						//LK.birdy = LK.birdy - 5;
    						y = y+1;
    					}
    				}
    				else
    				{	
    					if(LK.birdy != LK.birdoy)
    					{
    						LK.birdy = LK.birdy + 3.125;
    						//alert(LK.birdy);
    					}
    				}
    				
    				b.drawImage(birdl, LK.birdx, LK.birdy,10,10);
    				//$('#front').append(LK.birdx + ' ');
    			}
    			else
    			{
    				y = 0;
    				x = 0;
    				//alert(LK.birdx);
    				//LK.birdy = LK.birdy + 6.25;
    				b.drawImage(birdl, LK.birdx, LK.birdy,10,10);
    				clearInterval(interv);
    			}
    			//end draw
    			
    		}
    		else
    		{
    			clearInterval(interv);
    			LK.origx = LK.birdox + 25;
    			//LK.origy = LK.birdoy - 25;
    			LK.origy = LK.birdoy - 6.25;
    			y = 0;
    			x = 0;
    			interv = setInterval("LK.rmove()", 50);
    		}
    
    	}
    }
    Thats what i've got, and it works! Well it works for one object anyways.

    I tried using an array, but to no success. Im guessing i could read the drawImage statements into an array then read the array in a separate function drawing the images in sequence.

    Does anyone have a better suggestion?

  • #6
    New Coder
    Join Date
    Jan 2010
    Location
    Wisconsin
    Posts
    24
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Quote Originally Posted by disastro View Post
    Well, the best way is to keep everything seperate. Keep your animated object seperate from the canvas.

    In the following example, we will have one image (this means we don't need to wait for more than one image to load). The image is 64px by 32px. The region from 0,0 to 32,32 will contain frame 1 and the region from 32,0 to 64,32 will contain frame 2. We will use drawImage() to slice the appropriate frame from the image. We flip between the two frames by checking the value of a switch(toggle). Once we draw the frame, we will flip the toggle so the next frame will be rendered (rather than the same one over and over).

    Obviously this only works with a 2 frame animation.
    Code:
    // Our animated object
    Bird = new function() {
        // Set up animation frames
        this.image = new Image();
        // Our bird image will be 64px by 32px
        this.image.src = "bird.png"
        // Toggle for different frames
        this.state = false;
        return this;
    }
    
    function drawFrame(animObject,ctx) {
        // Clear our canvas
        ctx.clearRect(0,0,width,height);
        // If state==true then draw frame 1
        if(animObject.state) ctx.drawImage(animObject.image,0,0,32,32,0,0,32,32);
        // If state==false draw frame 2
        if(!animObject.state) ctx.drawImage(animObject.image,32,0,32,32,0,0,32,32);
        // Toggle the frame
        animObject.state = !animObject.state;
    }
    
    // The size of our canvas (needed by drawFrame and to resize canvas)
    width = 32;
    height = 32;
    
    // Set up the canvas. Assumes page has a canvas element called mycanvas
    canvas = document.getElementById("mycanvas");
    canvas.width = width;
    canvas.height = height;
    
    // Get the context
    context = canvas.getContext("2d");
    
    // Create a new animated bird
    myBird = new Bird();
    
    // Once the bird image is loaded ...
    myBird.image.onload = function() {
        // Draw a frame every 500 milliseconds
        setInterval("drawFrame(myBird,context)",500);
    }
    The image you use should look like this:
    Code:
    ---------------------------------
    |               |               |
    |       A       |       B       |
    |               |               |
    ---------------------------------
    Sorry, ASCII art is not my strong suit. "A" is your first frame and is 32x32, "B" is your second frame and is also 32x32.

    We draw a frame once every 500ms. When we draw frame 1, we set frame 2 to be the next frame. Likewise, when we draw frame 2, we set frame 1 to be next.

    If you wanted to pause the animation, just use clearInterval().

    Hopefully you can use this approach in your project.
    Hmm after analyzing your code it would seem that i could adopt my existing code that that one just ignoreing the frames, so myBird - new Bird() would create a new instance that would not interfere with the current right?

  • #7
    Regular Coder
    Join Date
    Jul 2010
    Posts
    185
    Thanks
    3
    Thanked 42 Times in 42 Posts
    I think I'm following you now.

    I'll just use simple objects for the moment, rather than your structure. With any luck you can incorporate the ideas into your framework.

    One approach is as follows:
    Code:
    Bird = new function() {
        this.x = 0;
        this.y = 0;
    
        return this;
    }
    
    function moveBirds() {
        for(i=0;i<myBirds.length;i++) {
            myBirds[i].x += 25;
            myBirds[i].y += 25;
        }
    }
    
    function drawFrame() {
        moveBirds();
        context.clearRect(0,0,width,height);
    
        for(i=0;i<myBirds.length;i++) {
            context.drawImage(birdImage, myBirds[i].x, myBirds[i].y);
        }
    
    }
    
    canvas = document.getElementById("mycanvas");
    context = canvas.getContext("2d");
    canvas.width = width;
    canvas.height = height;
    
    birdImage = new Image();
    birdImage.src = "bird.png";
    
    myBirds = new Array();
    myBirds.push(new Bird());
    myBirds.push(new Bird());
    
    setInterval("drawFrame()",1000);
    What we do here is create an array, we then add as many "Bird" objects to that array as we want. We call a function called "moveBirds()" before we draw the images. There should be more to this function than I gave above (it just moves them diagonally - start position is the same too). The moveBirds function loops through the array of birds, determines where each one should be (based on whatever rules you like). We then set the x and y coordinates for each object.

    We can then call drawFrame(). This loops through the object array and draws an image on the canvas for each object (using that object's precalculated x and y position).

    You will probably want to have a function to compute the new x and y values for each object (limiting them to within the canvas too). You may also want to store direction, image etc within the Bird object.

    Hope this points you in the right direction.

  • #8
    Regular Coder
    Join Date
    Jul 2010
    Posts
    185
    Thanks
    3
    Thanked 42 Times in 42 Posts
    Quote Originally Posted by Rebelj12a View Post
    Hmm after analyzing your code it would seem that i could adopt my existing code that that one just ignoreing the frames, so myBird - new Bird() would create a new instance that would not interfere with the current right?
    Sorry, was writing the post above - didn't see your new one.

    Like in my post above, you can simply create an array to store as many instances of "Bird" as you like. You can loop through this array to compute the next position of each object. Then when you want to draw a frame, you clear the canvas, loop through your object array and draw an image at each objects new x and y position.

    The whole animation/game coding thing can get very confusing very quickly. Explainations tend to be wordy too
    I'm not great at explaining it clearly either!

    Of course, there are other ways you could approach the problem. This is by no means the only way.

  • #9
    New Coder
    Join Date
    Jan 2010
    Location
    Wisconsin
    Posts
    24
    Thanks
    2
    Thanked 0 Times in 0 Posts
    Yep we're both definitely on the same page. I'll post some results. *crosses fingers*

  • #10
    Regular Coder
    Join Date
    Jul 2010
    Posts
    185
    Thanks
    3
    Thanked 42 Times in 42 Posts
    Any developments Rebelj12a?

    It's good to see some HTML5 work being done. The more people use it, the more pressure is on MS to write a browser which actually implements a common standard for once.


  •  

    LinkBacks (?)


    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •