0

EDIT: solution some lines above.

I'm trying to have bouncing pictures with html5, canvas and some jQuery. I've successfully made some balls bouncing, but I can't figure out how to draw pictures instead of simple 'particles'.

I've tried in different ways, but actually I think I'missing something. I post the whole html so you can just copy/paste it easily.

Under my try there is a commented section with working bouncing balls.

Thank you so much!

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>HTML5 Canvas Explode Demo</title>
<link rel="stylesheet" href="styles.css" />
<meta name="viewport" content="width=320 initial-scale=1.0, user-scalable=no" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<style type="text/css">
* {
    margin: 0; padding: 0;
}

html, body {
    width: 100%;
    height: 100%;
}

canvas {
    display: block;
    background: whiteSmoke;
    width: 100%;
    height: 100%;
}
#presentation{
    position: fixed;
    background: rgba(0,0,0,0.7);
    width: 100%;
    height: 70px;
    box-shadow: 7px 7px 13px rgba(0,0,0,0.3);
    color: white;
    font-family:futura;
    font-size: 30px;
    padding-left: 50px;
    padding-top: 10px;
}
</style>

</head>
<body>
<div id="presentation">Bouncing Baaaaalls!</div>
<canvas id="output" ></canvas>



<script type="text/javascript">


        (function() {
        window.requestAnimationFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(f){window.setTimeout(f,40/60)
            }}});

        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext('2d');

        function Particle() {
            var W = canvas.width = window.innerWidth;
            var H = canvas.height = window.innerHeight;
            this.radius = 20;
            this.x = parseInt(Math.random() * W);
            this.y = H;

            this.color = 'rgb(' +
            parseInt(Math.random() * 255) + ',' +
            parseInt(Math.random() * 255) + ',' +
            parseInt(Math.random() * 255) + ')';


            if (this.x > W/2 ){

                this.vx = Math.random() * (-15 - -5) + -5;

            }else{

                this.vx = Math.random() * (15 - 5) + 5;

            }


            this.vy = Math.random() * (-32 - -25) + -25;


            this.draw = function() {

                var img = new Image();
                img.src = 'troll1.png';
                ctx.beginPath();
                ctx.fillStyle = "rgb(255,255,255)";
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                ctx.closePath();

                ctx.beginPath();
                ctx.arc(this.x, this.y, 20, 0, 6.28, false); 
                ctx.clip(); 
                ctx.stroke();
                ctx.closePath();
                ctx.drawImage(img, 0, 0);

                //  WORKING PARTICLES STARTS HERE

                // ctx.fillStyle = this.color;

                // ctx.beginPath();

                // ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
                // ctx.fill();


                // ctx.closePath();

                //  WORKING PARTICLES ENDS HERE


            };

        }
        var particle_count = 20;  
        var particles = [];



        // Now lets quickly create our particle
        // objects and store them in particles array
        for (var i = 0; i < particle_count; i++) {
            var particle = new Particle();
            particles.push(particle);
        }

        function renderFrame() {


            requestAnimationFrame(renderFrame);

            // Clearing screen to prevent trails
            var W = canvas.width = window.innerWidth;
            var H = canvas.height = window.innerHeight;
            ctx.clearRect(0, 0, W, H);

            particles.forEach(function(particle) {

                // The particles simply go upwards
                // It MUST come down, so lets apply gravity
                particle.vy += 1;

                // Adding velocity to x and y axis
                particle.x += particle.vx;
                particle.y += particle.vy;

                // We're almost done! All we need to do now
                // is to reposition the particles as soon
                // as they move off the canvas.
                // We'll also need to re-set the velocities

                if (
                    // off the right side
                    particle.x + particle.radius > W ||
                    // off the left side
                    particle.x - particle.radius < 0 ||
                    // off the bottom
                    particle.y + particle.radius > H
                ) {

                    // If any of the above conditions are met
                    // then we need to re-position the particles
                    // on the base :)


                    // If we do not re-set the velocities then
                    // the particles will stick to base :D

                    // Velocity X
                    particle.x = parseInt(Math.random() * W);
                    particle.y = H;
                    if (particle.x > W/2 ){

                        particle.vx = Math.random() * (-15 - -5) + -5;

                    }else{

                        particle.vx = Math.random() * (15 - 5) + 5;


                    }
                    particle.vy = Math.random() * (-32 - -28) + -28;


                }

                particle.draw();

            });
        }

        $(document).ready(function(){


            renderFrame();

        }); 


</script>
</body>
</html>

EDIT WITH SOLUTION: First, thanks to markE

I edited the code as he said, the problem was actually about timing (and understanding what I was doing). His answer really helped me a lot.

The image was not moving because I didn't told it to do that actually ( with ctx.drawImage(img, this.x, this.y)).

NOTE: For debugging canvas rendering with chrome take a look at HTML5 canvas inspector?

So here is the working (and ultra commented, thanks for the lesson markE) code for bouncing troll faces (put a troll1.png picture in the same folder):

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>HTML5 Canvas Explode Demo</title>
<!--    <link rel="stylesheet" href="styles.css" /> --> <meta name="viewport" content="width=320 initial-scale=1.0, user-scalable=no" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>

<style type="text/css">
* {
    margin: 0; padding: 0;
}

html, body {
    width: 100%;
    height: 100%;
}

canvas {
    display: block;
    background: whiteSmoke;
    width: 100%;
    height: 100%;
}
#presentation{
    position: fixed;
    background: rgba(0,0,0,0.7);
    width: 100%;
    height: 70px;
    box-shadow: 7px 7px 13px rgba(0,0,0,0.3);
    color: white;
    font-family:futura;
    font-size: 30px;
    padding-left: 50px;
    padding-top: 10px;
}
</style>

</head>
<body>
<div id="presentation">Bouncing Baaaaalls!</div>
<canvas id="output" ></canvas>



<script type="text/javascript">


(function() {
    //define the animation refresh (frame rendering) with built-in browser timing
    window.requestAnimationFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(f){window.setTimeout(f,40/60)
        }}});

//define some variables: canvas, context, img to put inside the context and an array of bouncing objects
        var canvas = document.querySelector('canvas');
        var ctx = canvas.getContext('2d');
        var img = new Image();
        //IMPORTANT: Wait for the picture to be loaded!
        img.onload = function(){
                alert('troll1 is LOADED.');

                beginAnimation();
        };
        //yes, the src goes after
        img.src = 'troll1.png';

        //how many bouncing objects?
        var particle_count = 4;  
        var particles = [];
        var particle;

        function Particle() {

            //define properties of a bouncing object, such as where it start, how fast it goes

            var W = canvas.width = window.innerWidth;
            var H = canvas.height = window.innerHeight;
            this.radius = 20;
            this.x = parseInt(Math.random() * W);
            this.y = H;

            //Uncomment for coloured particles: 

            // this.color = 'rgb(' +
            // parseInt(Math.random() * 255) + ',' +
            // parseInt(Math.random() * 255) + ',' +
            // parseInt(Math.random() * 255) + ')';

            //end coloured particles

            if (this.x > W/2 ){

                this.vx = Math.random() * (-15 - -5) + -5;

            }else{

                this.vx = Math.random() * (15 - 5) + 5;

            }


            this.vy = Math.random() * (-32 - -25) + -25;

            //we will call this function to actually draw the bouncing object at EVERY FRAME

            this.draw = function() {
                // Bouncing pictures were not bouncing because there were no this.x this.y . Shame on me. 

                 ctx.drawImage(img,this.x,this.y);


                // WORKING PARTICLES STARTS HERE

                // ctx.fillStyle = this.color;

                // ctx.beginPath();

                // ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
                // ctx.fill();


                // ctx.closePath();

                //WORKING PARTICLES ENDS HERE


            };

        }



        function renderFrame() {

            //RENDER THE PARTICLEEEEEEES!

            requestAnimationFrame(renderFrame);

            // Clearing screen to prevent trails
            var W = canvas.width = window.innerWidth;
            var H = canvas.height = window.innerHeight;
            ctx.clearRect(0, 0, W, H);

            particles.forEach(function(particle) {

                // The bouncing objects simply go upwards
                // It MUST come down, so lets apply gravity
                particle.vy += 1;

                // Adding velocity to x and y axis
                particle.x += particle.vx;
                particle.y += particle.vy;

                // We're almost done! All we need to do now
                // is to reposition the bouncing objects as soon
                // as they move off the canvas.
                // We'll also need to re-set the velocities

                if (
                    // off the right side
                    particle.x + particle.radius > W ||
                    // off the left side
                    particle.x - particle.radius < 0 ||
                    // off the bottom
                    particle.y + particle.radius > H
                ) {

                    // If any of the above conditions are met
                    // then we need to re-position the bouncing objects
                    // on the base :)


                    // If we do not re-set the velocities then
                    // the bouncing objects will stick to base :D

                    // Velocity X
                    particle.x = parseInt(Math.random() * W);
                    particle.y = H;
                    if (particle.x > W/2 ){

                        particle.vx = Math.random() * (-15 - -5) + -5;

                    }else{

                        particle.vx = Math.random() * (15 - 5) + 5;


                    }
                    particle.vy = Math.random() * (-32 - -28) + -28;


                }

                particle.draw();

            });
        }

        function beginAnimation(){
                    //create the particles and start to render them

                   for (var i = 0; i < particle_count; i++) {
                        particle = new Particle();
                        particles.push(particle);
                    }

                    //BOUNCE MOFOS!
                    renderFrame();

            }


</script>

Community
  • 1
  • 1
Edoardoo
  • 2,739
  • 4
  • 18
  • 27
  • Please don't add "SOLVED" to your question's title. If your question has been answered, please mark the answer as accepted. – j08691 May 07 '13 at 17:37

1 Answers1

1

You're not waiting for troll1.png to load before trying to draw it.

Var img=new Image();
img.onload=function(){
        beginMyAnimation();
}
img.src=”troll1”;
alert(“troll1 is not loaded yet.”);
function beginAnimation(){
        ….
        ctx.drawImage(img,0,0);
        ….
}

The order of execution is like this:

First var img=new Image().

Javascript creates a new image object and puts a reference in img.

Second img.onload….

Javascript doesn’t execute this code yet. It just takes note that onload must be executed after troll1.jpg has successfully been loaded into the new image object.

Third img.src=”something.jpg”.

Javascript immediately begins loading troll1.jpg.

Since loading will take a while, Javascript also continues executing any code that follows.

Fourth alert(“Image is not loaded yet.”);

Javascript displays this alert message. Note that troll1.jpg has not been loaded yet. Therefore, any code that tried to use the image now would fail—no image yet!

Fifth img.onload.

Javascript has finally fully loaded troll1.jpg so it executes the onload function.

Sixth beginMyAnimation()

Javascript will finally execute beginAnimation(). At this point any code that tries to use the image will succeed. You can do ctx.drawImage(img,0,0) will succeed now.

So rearrange all your setup code inside in beginAnimation(). Finally, put renderFrame() last in beginAnimation().

markE
  • 102,905
  • 11
  • 164
  • 176
  • Why the img.src is after the onload? I mean, can I put it inside the onload? Should I put the drawImage(img, 0,0) inside the onload? – Edoardoo May 05 '13 at 10:48
  • Tried but it doesn't work in the script. It works on a clean empty script instead. Any ideas? – Edoardoo May 05 '13 at 12:18
  • See my revised answer which explains the image loading sequence in more detail. – markE May 05 '13 at 18:17
  • OK, I'll try as soon as I can. Thank you so much for being so 'verbose', it really helps clarify. – Edoardoo May 06 '13 at 16:34
  • Wooo! It loads the picture in the ctx now, but it's not 'bouncing'. I can't figure out why... Is there any html5 canvas debugging software? NOTE: Same code (modified as you suggested) with particles rendering (as before) works. Any idea? I should definitely offer you a beer... – Edoardoo May 07 '13 at 17:09
  • Done! Solution in the edited answer, thanks again for your help. – Edoardoo May 07 '13 at 17:37