HTML5 Canvas Crazy Balls

A few months ago I developed a small javascript application that renders ‘crazy balls’ in HTML5 canvas. The balls move in random directions, change size and direction at random times. When they hit the borders of the canvas they bounce and eventually change their size.  See below the application in action.

Source Code

Find below the source code. The code is pretty simple and self-explanatory. If you have any question or suggestion, please drop a comment.

<!DOCTYPE html>
<html>
<head>
  <title>HTML5 Canvas Crazy Balls</title>

  <script>
    function floatEquals(v1,v2,delta) {
      return Math.abs(v1 - v2) <= delta;
    }

    function Ball(ctx,maxRadius) {
      this.calcTargetPoint = function() {
        this.radius = Math.random() * this.maxRadius + 1
        this.maxX = ctx.canvas.width - this.radius
        this.maxY = ctx.canvas.height - this.radius

        this.targetX = Math.random() * this.maxX
        this.targetY = Math.random() * this.maxY

        var speed = Math.random() * 50 + 50
        this.velX = (this.targetX - this.x) / speed
        this.velY = (this.targetY - this.y) / speed

        var r = Math.floor(Math.random() * 155 + 100)
        var g = Math.floor(Math.random() * 155 + 100)
        var b = Math.floor(Math.random() * 155 + 100)
        this.fillColor = "rgb(" + r + "," + g + "," + b + ")"
      }

      this.update = function() {
        var needNewTarget = false;

        this.x += this.velX
        this.y += this.velY

        if( this.x <= this.radius ) {
          this.x = this.radius;
          needNewTarget = true;
        }
        if( this.y <= this.radius ) {
          this.y = this.radius;
          needNewTarget = true;
        }
        if( this.x >= this.maxX ) {
          this.x = this.maxX;
          needNewTarget = true;
        }
        if( this.y >= this.maxY ) {
          this.y = this.maxY;
          needNewTarget = true;
        }
        if( floatEquals(this.x,this.targetX,0.9) && floatEquals(this.y,this.targetY,0.9) ) {
          needNewTarget = true;
        }

        if( needNewTarget ) {
          this.calcTargetPoint();
        }
      }

      this.draw = function() {
        this.ctx.fillStyle = this.fillColor;
        this.ctx.beginPath();
        this.ctx.arc(this.x,this.y,this.radius,0,2*Math.PI,false);
        this.ctx.lineWidth = 3;
        this.ctx.stroke();
        this.ctx.fill();
      }

      this.ctx = ctx
      this.maxRadius = maxRadius
      this.radius = Math.random() * maxRadius + 1

      this.maxX = ctx.canvas.width - this.radius
      this.maxY = ctx.canvas.height - this.radius

      this.x = Math.random() * this.maxX
      this.y = Math.random() * this.maxY

      this.calcTargetPoint()
    }

    window.onload = function() {
      canvas = document.getElementById("tutorial")
      if( canvas && canvas.getContext ) {
        ctx = canvas.getContext("2d")
        initDemo()
        setInterval(loop,33)
      }
    }

    function initDemo() {
      gradient = ctx.createLinearGradient(0,0,0,300);
      gradient.addColorStop(0,"#202020");
      gradient.addColorStop(1,"#304030");

      balls = new Array(32)
      for( var i = 0; i < balls.length; i++ ) {
        balls[i] = new Ball(ctx,10)
      }
    }

    function loop() {
      ctx.fillStyle = gradient
      ctx.fillRect(0,0,canvas.width,canvas.height)

      for( var i = 0; i < balls.length; i++ ) {
        balls[i].update()
        balls[i].draw()
      }
    }
  </script>
</head>
<body>
  <canvas id="tutorial" width="500" height="400">
    Your browser does not support the HTML5 Canvas element.
    Please, update your browser.
  </canvas>
</body>
</html>

If you like this article, please click one of the buttons below to share the article.

  1. A little bit pointless, but still it’s nice to watch people using fresh technologies.

    I’ve analysed 2 of your canvas projects and I’ve got a little advice for you. Check out the requestAnimationFrame function (instead of using setInterval( loop, 33 )). It’s better for CPU as it uses browser framing.

Leave a Comment

Notify me of followup comments via e-mail. You can also subscribe without commenting.