RSS michelepasin.org / code, music, words

Words / blog / 25 August 2011

First steps with Canvas and HTML5


I've been postponing experimenting with HTML5 for quite a while, so today I finally set aside a few hours to play with it. This is a very simple example of the graphic effects you can create using JavaScript and the HTML5 canvas element.

Note that the examples below will work only on HTML5-compatible browsers, such as the latest versions of Chrome or Firefox.

1. Setting up a canvas and drawing some lines on it

This is easily done using the moveTo and lineTo functions. Let's create a simple symmetrical geometrical shape.

Your browser does not support the canvas element.

var c=document.getElementById("myCanvas1"); var cxt=c.getContext("2d"); var i=0;

for (i=1;i<=5;i++) { cxt.moveTo(0, 400); cxt.lineTo(100, i \* 40); cxt.lineTo(300, i \* 60); cxt.lineTo(400, i \* 30); cxt.lineTo(500, i \* 60); cxt.lineTo(700, i \* 40); cxt.lineTo(800, 400); }

cxt.stroke();

Here's the source code:

<!DOCTYPE HTML>
<html\>
<body\>

<canvas id\="myCanvas1" width\="800" height\="400" style\="border:1px dashed #c3c3c3;"\>
Your browser does not support the canvas element.
</canvas\>

<script type="text/javascript"\>

var c\=document.getElementById("myCanvas1");
var cxt\=c.getContext("2d");
var i\=0;

for (i\=1;i<=5;i++)
{
cxt.moveTo(0, 400);
cxt.lineTo(100, i \* 40);
cxt.lineTo(300, i \* 60);
cxt.lineTo(400, i \* 30);
cxt.lineTo(500, i \* 60);
cxt.lineTo(700, i \* 40);
cxt.lineTo(800, 400);
}

cxt.stroke();

</script\>

</body\>
</html\>

2. Creating a mirroring effect

Now we can increase the size of the canvas to 800 and replicate these lines at the bottom of the canvas to achieve a 'mirroring' effect. Since we know the maximum Y value of the canvas (800), let's just add another loop that draws the same lines but inverts the Y position. This is easily achieved by subtracting the constant-dependent parameter from the maximum value of Y.

var c=document.getElementById("myCanvas2"); var cxt=c.getContext("2d"); var i=0;

for (i=1;i<=5;i++) { cxt.moveTo(0, 400); cxt.lineTo(100, i \* 40); cxt.lineTo(300, i \* 60); cxt.lineTo(400, i \* 30); cxt.lineTo(500, i \* 60); cxt.lineTo(700, i \* 40); cxt.lineTo(800, 400); }

for (i=5;i>=1;i--) { cxt.moveTo(0, 400); cxt.lineTo(100, 800 - (i \* 40)); cxt.lineTo(300, 800 - (i \* 60)); cxt.lineTo(400, 800 - (i \* 30)); cxt.lineTo(500, 800 - (i \* 60)); cxt.lineTo(700, 800 - (i \* 40)); cxt.lineTo(800, 400); }

cxt.stroke();

This is how the new source code looks like:

var c\=document.getElementById("myCanvas2");
var cxt\=c.getContext("2d");
var i\=0;

for (i\=1;i<=5;i++)
{
cxt.moveTo(0, 400);
cxt.lineTo(100, i \* 40);
cxt.lineTo(300, i \* 60);
cxt.lineTo(400, i \* 30);
cxt.lineTo(500, i \* 60);
cxt.lineTo(700, i \* 40);
cxt.lineTo(800, 400);
}

for (i\=5;i\>=1;i\--)
{
cxt.moveTo(0, 400);
cxt.lineTo(100, 800 \- (i \* 40));
cxt.lineTo(300, 800 \- (i \* 60));
cxt.lineTo(400, 800 \- (i \* 30));
cxt.lineTo(500, 800 \- (i \* 60));
cxt.lineTo(700, 800 \- (i \* 40));
cxt.lineTo(800, 400);
}

cxt.stroke();

3. Adding more graphical interest

Finally, let's parameterize the construction of this geometrical pattern a bit more by including everything in another loop and using this new counter to increment the points' ordinate position. We'll add a new variable y and use it to run the external loop 20 times. Here's the result:

var c=document.getElementById("myCanvas3"); var cxt=c.getContext("2d"); var i=0; var y=0;

for (y=1;y<=20;y++) { for (i=1;i<=5;i++) { cxt.moveTo(0, 400+y); cxt.lineTo(100, i \* (40+y)); cxt.lineTo(300, i \* (60+y)); cxt.lineTo(400, i \* (30+y)); cxt.lineTo(500, i \* (60+y)); cxt.lineTo(700, i \* (40+y)); cxt.lineTo(800, 400+y); }

for (i=5;i>=1;i--) { cxt.moveTo(0, 400); cxt.lineTo(100, 800 - (i \* (40+y))); cxt.lineTo(300, 800 - (i \* (60+y))); cxt.lineTo(400, 800 - (i \* (30+y))); cxt.lineTo(500, 800 - (i \* (60+y))); cxt.lineTo(700, 800 - (i \* (40+y))); cxt.lineTo(800, 400+y); }

}

cxt.stroke();

Not too bad, right? This last modification to the code looks like this:

var c\=document.getElementById("myCanvas3");
var cxt\=c.getContext("2d");
var i\=0;
var y\=0;

for (y\=1;y<=20;y++)
{

    for (i\=1;i<=5;i++)
    {
    cxt.moveTo(0, 400+y);
    cxt.lineTo(100, i \* (40+y));
    cxt.lineTo(300, i \* (60+y));
    cxt.lineTo(400, i \* (30+y));
    cxt.lineTo(500, i \* (60+y));
    cxt.lineTo(700, i \* (40+y));
    cxt.lineTo(800, 400+y);
    }

    for (i\=5;i\>=1;i\--)
    {
    cxt.moveTo(0, 400);
    cxt.lineTo(100, 800 \- (i \* (40+y)));
    cxt.lineTo(300, 800 \- (i \* (60+y)));
    cxt.lineTo(400, 800 \- (i \* (30+y)));
    cxt.lineTo(500, 800 \- (i \* (60+y)));
    cxt.lineTo(700, 800 \- (i \* (40+y)));
    cxt.lineTo(800, 400+y);
    }

}

cxt.stroke();

Cool! I'd like to know more

Yes, I agree. This opens up a new world for web-based graphics, and I've just scratched the surface! In particular, I'd like to see how this type of graphical component can be used to compose visualizations in the digital humanities—provided more interactivity is added to them.

Here are a couple of learning resources I found useful:

Michele Pasin. First steps with Canvas and HTML5. Blog post on www.michelepasin.org. Published on Aug. 25, 2011.

2026

2023

2021

2020

2019

2017

2015

2014

2013

2012

2011

2010

2009

2008

2007

2006