Ajax Loader
×

Recreating Phase Beam in Canvas - Part 1

Recreating Android's ICS Phase Beam Live Wallpaper Using Canvas

Here's my first series of tutorials. In this series, you will learn how to recreate the Android's ICS Phase Beam Live Wallpaper using HTML5's canvas. This is the first part of this this series in which I will teach you how to create and animate the circles. In the next part, I will teach you about how to make the circles blur and create lines too.

Step 1 - Creating the canvas

So let's start by adding a canvas element into the HTML. We'll also need to include the jQuery.

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<canvas id="canvas"></canvas>

Now we need to add some CSS to prevent margins, paddings and visible scrollbars.

body {padding: 0px; margin: 0; overflow: hidden;}

Now you have created the canvas, you need to initialize it's context with JS.

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

Here, the getContext method initializes the canvas with a 2d context. You don't need to understand this much deeply. After creating the canvas, we need to set it's height and width equal to the window's height and width which can be simply done by:

var W = window.innerWidth, H = window.innerHeight;
canvas.width = W;
canvas.height = H;

Step 2 - Fill the canvas with a diagonal linear gradient

As now you have initialized the canvas, it's time to add a nice background to it. We'll star off with creating a linear gradient. The linear gradient can be created by using the following code.

var grad = ctx.createLinearGradient(0, 0, W, H);
grad.addColorStop(0, 'rgb(19, 105, 168)');
grad.addColorStop(0.9, 'rgb(0, 0, 0)');

The createLinearGradient function accepts four parameters which can be defined as (start position X, start position Y, end position X, end position Y), so we just passed the starting values as 0,0 and ending values as the width and height of the canvas so that the gradient covers the full window.

Now, the second and the third lines are used to add color stops to the gradient by using addColorStop method which is self-explanatory. To fill the canvas with the gradient we just created, we would need to do the following:

ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = grad;
ctx.fillRect(0,0,W,H);

The first line is to set the globalCompositeOperation to source-over so that the BG of current frame doesn't mix with the BG of previous frame. There are many values for globalCompositeOperation which you can learn about here.

The second line sets the fillStyle to the gradient we just created. You can also pass colors here, try passing "blue" instead of grad and see the result. The third line is for filling the canvas using a rectangle. The attributes are same as explained when we created the gradient. So now, you have a beautiful canvas background. Now we need to add some circles but before that, let's organize our code a little.

Move everything under window.onload = function() { //code here }. You'll get the following code

window.onload = function() {
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    //Set the dimensions of canvas equal to the window's dimensions
    var W = window.innerWidth, H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;

    //Create the gradient
    var grad = ctx.createLinearGradient(0, 0, W, H);
    grad.addColorStop(0, 'rgb(19, 105, 168)');
    grad.addColorStop(0.9, 'rgb(0, 0, 0)');
        
    //Fill the canvas with the gradient
    ctx.globalCompositeOperation = "source-over";
    ctx.fillStyle = grad;
    ctx.fillRect(0,0,W,H);
}

Also, when we will animate the circles, it would require to repaint the background in each frame so that it doesn't get merged with the circles or the background of previous frame. So, move the gradient code and the fill code under a new function draw() and then call it somewhere after the dimensions specifications.

window.onload = function() {
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");

    //Set the dimensions of canvas equal to the window's dimensions
    var W = window.innerWidth, H = window.innerHeight;
    canvas.width = W;
    canvas.height = H;

    draw();

    //Function to draw the background
    function draw() {
        //Create the gradient
        var grad = ctx.createLinearGradient(0, 0, W, H);
        grad.addColorStop(0, 'rgb(19, 105, 168)');
        grad.addColorStop(0.9, 'rgb(0, 0, 0)');
        
        //Fill the canvas with the gradient
        ctx.globalCompositeOperation = "source-over";
        ctx.fillStyle = grad;
        ctx.fillRect(0,0,W,H);
    }
}

Step 3 - Adding circles and animating them

The code looks much better and now we will create the circles and animate them. Start off by creating an empty array called circles and a function to create the circles with random properties. This function will be used to fill the circles array with circles having different properties like position, speed and radius. The code will look like

//Create an array of circles
var circles = []; 
for(var i = 0; i < 20; i++ ){
    circles.push(new create_circle());
}

//Function to create circles with different positions and velocities
function create_circle() {
    //Random Position
    this.x = Math.random()*W;
    this.y = Math.random()*H;
    
    //Random Velocities but same direction. 
    this.vx = Math.random()*1;
    this.vy = -this.vx;
    
    //Random Radius
    this.r = 10 + Math.random()*50;
}

Add this code above the draw() function we created in the previous step. Now we need to place the circles on the canvas. To do this, we will modify our draw() function and the following code to it at the end. The function create_circle() is used to create a circle with random values / properties. Try to experiment with these to get different results. You can change the direction by passing a random value to this.vy variable.

//Fill the canvas with the circles
for(var j = 0; j < circles.length; j++) {
    var c = circles[j];
    
    //Draw the circle and it with the blur grad
    ctx.beginPath();
    ctx.globalCompositeOperation = "lighter";       
    ctx.fillStyle = grad;
    ctx.arc(c.x, c.y, c.r, Math.PI*2, false);
    ctx.fill();
    
    //Lets use the velocity now
    c.x += c.vx;
    c.y += c.vy;
    
    //To prevent the circles from moving out of the canvas
    if(c.x < -50) c.x = W+50;
    if(c.y < -50) c.y = H+50;
    if(c.x > W+50) c.x = -50;
    if(c.y > H+50) c.y = -50;
}

Here, to draw a circle, we have used the canvas function .arc(x offset, y offset, radius, angle, counterclockwise?). You will notice that here, globalCompositeOperation has the value lighter, this is to make the circles transparent. Try using different values in here like darker. The circle is created by first calling the beginPath() function, then we set the globalCompositeOperation, then we set the fill style to the gradient we created earlier, then we create the circle and finally we fill the circle with the gradient.

After this, we increment the position of the circles according to their velocites and then there are some conditions to prevent them from moving outside the canvas. If they move outside, they'll be moved at the start so by this way, we won't have to add more circles to the canvas.

Now the final step is to modify the calling of our draw() function. We want to animate the frames so here, we will use the setInterval() function. The final code will look like this

window.onload = function() {
    
    //Create canvas and initialize it's context
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    
    //Set the dimensions of canvas equal to the window's dimensions
    var W = window.innerWidth, H = window.outerHeight;
    canvas.width = W;
    canvas.height = H;
    
    //Create an array of circles
    var circles = []; 
    for(var i = 0; i < 20; i++ ){
        circles.push(new create_circle());
    }

    //Function to create circles with different positions and velocities
    function create_circle() {
        //Random Position
        this.x = Math.random()*W;
        this.y = Math.random()*H;
    
        //Random Velocities
        this.vx = Math.random()*1;
        this.vy = -this.vx;
    
        //Random Radius
        this.r = 10 + Math.random()*50;
    }
    
    //Function to draw the background
    function draw() {
        //Create the gradient
        var grad = ctx.createLinearGradient(0, 0, W, H);
        grad.addColorStop(0, 'rgb(19, 105, 168)');
        grad.addColorStop(0.9, 'rgb(0, 0, 0)');
        
        //Fill the canvas with the gradient
        ctx.globalCompositeOperation = "source-over";
        ctx.fillStyle = grad;
        ctx.fillRect(0,0,W,H);

        //Fill the canvas with the circles
        for(var j = 0; j < circles.length; j++) {
            var c = circles[j];
    
            //Draw the circle and it with the blur grad
            ctx.beginPath();
            ctx.globalCompositeOperation = "lighter";       
            ctx.fillStyle = grad;
            ctx.arc(c.x, c.y, c.r, Math.PI*2, false);
            ctx.fill();
        
            //Lets use the velocity now
            c.x += c.vx;
            c.y += c.vy;
    
            //To prevent the circles from moving out of the canvas
            if(c.x < -50) c.x = W+50;
            if(c.y < -50) c.y = H+50;
            if(c.x > W+50) c.x = -50;
            if(c.y > H+50) c.y = -50;
        }
    }
    
    setInterval(draw, 25);

} 

Make sure you type all the code instead of copying and pasting. Also, as you write the code, try experimenting with different values to get some interesting results. You can add various Math functions to make the animation more interesting. Now show me your creations or if you have any question, then use the comment form below :)

In the next part, I will show how to make the circles blurry and create other particles like in the original live wallpaper.

Related:

×

Coding Preferences


HTML

CSS

Javascript

More

×

Your Default Settings - Preferences

×
×
×

Validations

(Errors from your JS or Pre-Processors code)

    HTML
    CSS
    JavaScript

    Recreating Phase Beam in Canvas - Part 1

    CSSDeck G+