Working with HTML5 Canvas

Introduction

One of the reasons for the popularity of the web is the graphical user

interface offered to the end users. Images, animations, fonts and other

interactive effects make a website appealing from an end user’s perspective. However,

one limitation that website developers often encounter is drawing graphics in

the browser. As a solution, developers often resort to Flash or Silverlight based plug-ins or generate

graphics on the fly at server side and then send it to the client. HTML5

does a great job in client side graphic rendering by offering what is known as canvas.

The actual drawing can be carried out using JavaScript code and certain new

graphic objects. Understanding HTML5 canvas and associated JavaScript objects

is important for any ASP.NET developer and

this article teaches you just that.

What is HTML5 Canvas?

HTML5 canvas is very similar to a real life drawing canvas in that it allows

you to draw shapes, text, backgrounds and many other drawing operations. Of

course, HTML5 canvas

is browser based and is measured in pixels. At HTML markup level, canvas is

represented by the <canvas> tag. A basic usage of <canvas> tag is

shown below:

<canvas id="myCanvas" width="500" height="500"></canvas>

The canvas tag, by itself, will not draw anything on the screen. You will

need to use some JavaScript code to draw on the canvas. Note that although the

above example sets the width and height properties in the markup itself, you

can also set them via canvas DOM element or CSS.

Canvas can be of great use while rendering graphics on the client side

dynamically. For example, consider that you are allowing the end user to design

simple logos or charts dynamically. Users can play with the data (such as logo

text, height and width or values to be plotted on the chart) and the result is

immediately visible on the screen. You can then save the user inputs on the

server side once the drawing process is complete.

Rendering Context Object

At the heart of drawing on the canvas is a rendering context object.

Rendering context object is responsible for displaying shapes and text on the

canvas. There can be more than one rendering context (say 2D context and 3D

context). Your JavaScript code can get hold of the rendering context using the

getContext() DOM method. The following piece of code shows how:

var myCanvas = document.getElementById('myCanvas');

var myContext = myCanvas.getContext("2d");

As you can see the getContext() method takes a type of context to use (2D in

this case) as its parameter. Once a rendering context is available, your code

can call various drawing methods on the context. The following table lists some

of the common methods of rendering context object:

Method 

Description 

fillRect()

Draws a filled rectangle 

strokeRect() 

Draws a rectangular outline 

clearRect() 

Clears a rectangular region of the canvas 

lineTo() 

Draws a straight line 

arc() 

Draws an arc or circle

moveTo() 

Moves the current drawing point to a specified

location 

beginPath() 

Initiates drawing a path 

closePath() 

Marks the end of the path drawing operation 

stroke() 

Perform actual drawing of a path in outline fashion 

fill() 

Perform actual drawing of a path in filled fashion 

fillText()

Draws a string of characters on the canvas

Drawing on Canvas

Now that you have some idea about HTML5 canvas and various drawing

operations, let’s develop a simple web page that makes use of many of the above

drawing methods. 

Create a new web page in any text editor or HTML designer (such as Microsoft

Expression Web) and add the <canvas> tag as shown previously. Then add

the following <script> block in the head section of the page.

window.onload = function () {

   var myCanvas = document.getElementById('myCanvas');

   var context = myCanvas.getContext('2d');

   ...

}

To begin with, you will draw a rectangle with left and top coordinates equal

to (10,10) and width and height of 200 and 100 pixels respectively. Remember

that these coordinates are with respect to the canvas you defined earlier.

context.fillRect(10,10, 200, 100);

The fillRect() method takes x coordinate, y coordinate, width and height of

the rectangle and draws a filled rectangle as shown below:

The fillRect() method draws a filled rectangle

Figure 1: The fillRect() method draws a filled rectangle

To draw a circle with radius 50 and center at coordinates 100 and 200 you

will write the following piece of code:

 context.arc(100, 200, 50, 0, 2 * Math.PI, false);

context.fill();

The arc() method draws an arc as per the given specifications. The first two

parameters indicate the coordinates of the center. The third parameter is the

radius of the circle. The next two parameters (0 and 2* Math.PI) represent the

start angle and end angle for the start and end points of the arc in radians as

measured from the X axis. The last boolean parameter decides whether the arc

will be drawn in anticlockwise direction (true) or clockwise direction (false).

Note that you must call fill() method to draw the arc (or stroke() method if

you wish just the outline rather than filled arc). The following figure shows

the circle drawn as a result of the preceding code:

The circle drawn as a result of the preceding code

Figure 2: The circle drawn as a result of the preceding code

To draw a line at coordinates 125,125 you will write:

context.moveTo(125,125);

context.lineTo(125,45);

context.stroke();

Note that the coordinates of the start point of the line are governed by the

"current" position on the canvas. In the above code the moveTo()

method marks the current drawing position to 125,125. The lineTo() method

accepts the coordinates of the end point of the line. Thus the start point of

the line is at 125,125 and end point at 125, 45. The stroke() method performs

the actual drawing operation.

The stroke() method performs the actual drawing operation.

Figure 3: The stroke() method performs the actual drawing operation.

Now let’s draw a triangle using a path operation.

context.beginPath();

context.moveTo(125,350);

context.lineTo(100,600);

context.lineTo(45,450);

context.closePath();

context.stroke();

The beginPath() method initializes drawing of the path. The first call to

moveTo() method shifts the current drawing position to 125,350. The two calls

to lineTo() method then draw two sides of the triangle. The closePath() method

completes the triangle by completing the path.

The closePath() method completes the triangle by completing the path

Figure 4: The closePath() method completes the triangle by completing the path

Finally, let’s draw some text on the canvas.

context.font = '20pt Arial';

context.fillText('Drawing text on the Canvas', 0, 100);

The fillText() method does the job of outputting specified string at a

specific location (0,100). Notice that the font and font size of the text can

be controlled by setting the font property.

Draw some text on the canvas

Figure 5: Draw some text on the canvas

In the above example, you used the default rendering properties for the

shapes. You can customize the look and feel of the shapes with the help of

various properties. Have a look at the following fragment of code:

context.fillStyle = 'blue';

context.strokeStyle = 'blue';

context.lineWidth = 10;

context.shadowOffsetX = 5;

context.shadowOffsetY = 5;

context.shadowBlur = 10;

context.shadowColor = 'black';

context.font = '20pt Arial';

...

The above code sets the drawing color to blue using fillStyle and

strokeStyle properties. The lineWidth property governs the width of the line

used to draw shapes. The shadowOffsetX, shaddowOffsetY, shadowBlur and shadowColor

properties decide the respective behavior of shadow. The following figure shows

some of the above shapes after applying the styling properties.

Applying the styling properties

Figure 6: Applying the styling properties

Drawing Charts Using Canvas

Now let’s develop a more realistic example by plotting a pie chart on the

canvas. The pie chart will be drawn with some default values initially when the

page loads but you can get the values from the server via a web service or WCF

service. Begin by creating a new website in Visual Studio 2010. Add

a new web form and enter the following HTML markup into it (the following

markup has been trimmed to save some space. You can get the complete markup

from the code download.).

<!DOCTYPE html>

<html lang="en">

<head>

...

<script src="Scripts/jquery-1.4.4.js" type="text/javascript"></script>

...

<div>

<input type="button" value="Get Chart Data" id="Button1" />

...

<canvas id="myCanvas" width="400" height="500"></canvas>

...

<script type="text/javascript">

    var chartColors = ['red', 'green', 'blue', 'yellow', 'orange'];

    var chartData = [10, 20, 30, 40, 50];

    var chartLabels = ['Part 1', 'Part 2', 'Part 3', 'Part 4', 'Part 5'];

 

    function GetTotal() {

        var total = 0;

        for (var j = 0; j < chartData.length; j++) {

            total += chartData[j];

        }

        return total;

    }

 

    function DrawChart() {

        var canvas;

        var context;

        var angle = 0;

        var total = GetTotal();

 

        canvas = document.getElementById("myCanvas");

        context = canvas.getContext("2d");

        context.clearRect(0, 0, canvas.width, canvas.height);

 

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

            context.fillStyle = chartColors[i];

            context.beginPath();

            context.moveTo(200, 150);

            context.arc(200, 150, 150, angle, angle + (Math.PI * 2 * (chartData[i] / total)), false);

            context.lineTo(200, 150);

            context.fill();

            angle += Math.PI * 2 * (chartData[i] / total);

        }

 

        var offset = 350;

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

            context.fillStyle = chartColors[i];

            context.font = '10pt Arial';

            context.fillRect(10, offset, 20, 20);

            context.fillText(chartLabels[i] + ' - ' + chartData[i], 40, offset + 15);

            offset += 30;

        }

    }

 

    DrawChart();

</script>

...

The above markup defines a canvas of size 400 X 500. It also has a button at

the top that you will put to use later. The JavaScript code defines three

global arrays viz. chartColors, chartData and chartLabels. As the names suggest

they store colors of individual sectors of the chart, data with which the pie

chart is to be plotted and labels explaining sector colors. In the above

example you are using 5 values but you can easily increase or decrease them by

adding or removing values from these three arrays.

The GetTotal() function simply sums up the data values from the chartData

array. The total is later used in the DrawChart() function.

The DrawChart() function iterates through the chartData array and draws

individual arcs with the help of arc() function. Notice the use of beginPath(),

moveTo(), lineTo() and fill() methods we discussed earlier. Another for loop

iterates through chartColors array and draws legends for various sectors of the

chart. The following figure shows a sample run of the web form.

The DrawChart() function

Figure 7: The DrawChart() function

So far, you are using fixed set of values to plot the chart. Let’s change

our code so that it fetches the values by invoking a web method instead. The

web method that returns the chart data as an array of integers looks like this:

<script runat="server">

    [WebMethod]

    public static int[] GetChartData()

    {

        Random r = new Random();

        int[] data = new int[5];

        for (int i = 0; i < 5; i++)

        {

            data[i] = r.Next(10, 100);

        }

        return data;

    }

</script>

The GetChartData() web method fills an integer array with random integers

between 10 and 100. Of course, in a more real world scenario you will pick the

values from a database. 

You will invoke the web method using jQuery so ensure that you have added

jQuery library to your website.

<script src="Scripts/jquery-1.4.4.js" type="text/javascript"></script>

Then wire the click event handler for the "Get Chart Data" button

as shown below:

$(document).ready(function () {

    $("#Button1").click(OnGetData);

})

The OnGetData() function calls the GetChartData() web method as shown below:

function OnGetData(event) {

    var url = "default.aspx/GetChartData";

    successHandler = function (results) {

        chartData = results.d;

        DrawChart();

    }

    $.ajax({

        type: "POST",

        url: url,

        contentType: "application/json; charset=utf-8",

        dataType: "json",

        success: successHandler,

        error: function (err) {

            alert(err.status + " - " + err.statusText);

        }

    })

}

The OnGetData() function makes use of $.ajax() function to call the web

method. Notice how URL to the web method is specified as <web

form>/<web method name>. Once the web method returns, the code as

specified by successHandler will be invoked. The successHandler code

simply assigns the array returned by the web method to chartData global

variable. The chart is then redrawn by calling the DrawChart() method. (NOTE:

Detailed explanation of calling web methods using jQuery is beyond the scope of

this article.)

Run the web form and try clicking on the button a few times. Every time the

chart is re-drawn with new random values returned by the web method. 

Summary

Canvas and drawing features of HTML5 make it easy for developers to draw

shapes and text via client side JavaScript code. The <canvas> tag defines

an HTML5 canvas. Drawing operations can then be performed on the canvas using

various rendering context methods. This article gave you a peek inside these

drawing features. You also learned to draw a pie chart that fetches its values

from a web method.

More by Author

Must Read