Creating a picture gallery with HTML5 canvas

Displaying pictures in a gallery is something that so easy to do with one of the many jQuery Plugins, but what if you want to use the HTML5 canvas tag?

Capital FM recently created a HTML5 showcase page called Be A Star and at the bottom they show off a rather fancy image gallery. The gallery uses HTML5 canvas and below I’m going to show how you can create something like this yourself. If you want to see how they also used CSS3 check this post out.

The gallery that we are going to create

The canvas tag is like a bitmap, once we draw an image on the canvas we can’t go back and query that image to obtain it’s properties. Unlike DOM objects we can not simply animate them by altering their x and y coordinates. To animate using the canvas tag you create a loop and then 24 times per second (actually how often you like) you redraw the entire canvas.

If you want to animate an image it’s up to you to hold a reference to that image and then redraw the image by placing it in a different position on the canvas on every tick of the loop.

Because this is so complicated I’m going to use a nice little library called Easel.js.  The Easel JavaScript library provides a full, hierarchical display list, a core interaction model, and helper classes to make working with Canvas much easier.

To use Easel.js. in a page you will need to download the library from easeljs.com and then add the following scripts to the header of the document.

<script src=”../easeljs/utils/UID.js”></script><script src=”../easeljs/utils/SpriteSheetUtils.js”></script><script src=”../easeljs/display/SpriteSheet.js”></script><script src=”../easeljs/display/Shadow.js”></script><script src=”../easeljs/display/DisplayObject.js”></script><script src=”../easeljs/display/Container.js”></script><script src=”../easeljs/display/Stage.js”></script><script src=”../easeljs/display/Bitmap.js”></script><script src=”../easeljs/display/BitmapSequence.js”></script><script src=”../easeljs/utils/Tick.js”></script>

 

Next you will need to add a canvas element to the document

<body onload=”init()”><canvas id=”testCanvas” width=”980″ height=”580″></canvas></body>

 

You will also need to set the onload property of the body tag so that it will call a JavaScript function called init when the page loads.

Next we add the init function to the page.

var canvas; var stage; var pictures =new Array(5); var imageCount =0; function init() { canvas = document.getElementById(testCanvas); canvas.onmousemove = onMouseMove; stage =new Stage(canvas); for (i =0; i <= pictures.length -1; i++) { pictures[i] =new Image(); pictures[i].src =img/2.jpg; pictures[i].onload = imageLoaded; } Tick.addListener(window); }

 

Firstly in the function we will set a global variable called canvas and populate it with the the canvas element that’s on the page. We have declared the canvas variable just outside and above the init function.

Next we will attach the canvas elements onmousemove event to a new function called onMouseMove . We will create this function later and it will enable us to determine where the mouse is on the canvas and animate the picture gallery accordingly.

Next we populate the stage variable with a new Stage object. The stage object is part of the Easel.js library and is used to keep track of all of the objects that will be drawn on the canvas.

Next I have added a for loop that adds a number of images to an array called pictures. If you were doing this for real you would add your pictures here rather than adding a number of dummy images.

Finally I’ve added a listener to the Tick object. The tick object is part of the Easel library and provides a heartbeat to the project. On every beat of this heartbeat the library will  fire the function on the page called Tick.

Now you may have noticed that every time I have added a picture to the array I set the onload event of the image to a function called imageLoaded. When the image has successfully loaded this function is called. This is a mechanism to preload the images before attempting to add them to the canvas.

The function imageLoaded is called by each image. When a new image loads it increments the imageCount variable. When the imageCount variable is equal to the number of pictures we then call the function createBitMaps. The imageLoaded function ensures that all of our images are preloaded before we go to the createBitMaps function

function imageLoaded() { imageCount++; if (imageCount >= pictures.length) { createBitMaps(); } }

 

In the createBitMaps function we loop through each image and create a new bitmap. This bitmap is then added to to the stage object.

function createBitMaps() { var bitmap; for (i =0; i <= pictures.length -1; i++) { bitmap =new Bitmap(pictures[i]); bitmap.x =250* i; bitmap.y = canvas.height /2; bitmap.rotation =45* Math.random() |0; stage.addChild(bitmap); } }

 

First we create a new BitMap object then we set the x property of the bitmap. This is the horizontal co-ordinate that the image will have on the canvas.

For simplicity I have, in this loop, multiplied 250 by the loop counter and used this to set the x property, which will in-effect, lay the images out horizontally with a 250 pixel space between each image.

Next I have set the y property which is the vertical position of the image on the canvas and set it to be half the height of the canvas. This will put all of the images in the middle of the canvas.

I have then set the rotation property to a number between 0 and 45. This will insure that the images are randomly rotated between 0 and 45 degrees when the are drawn on the canvas.

Lastly I add the bitmap objet as a child of the stage object.

Now if we run the project nothing will happen and we will end up with a white screen. You see to get the stage object to draw its objects to the canvas we will need to add a function called tick. This function is called by the Tick object that we set up earlier.

It’s important at the end of the this function to fire the stage.tick function.

function tick() { stage.tick(); }

 

We should now see the images have appeared as expected on the canvas. However, when we move our mouse from left to right nothing happens as we haven’t told the onMouseMoveEvent to do anything.

function tick() { var direction =-(stage.mouseX - (canvas.width /2)) / ((canvas.width /2)/10) for (i =0; i <= pictures.length -1; i++) { stage.children[i].x = stage.children[i].x + direction; } stage.tick(); } function onMouseMove(e) { if (!e) { var e = window.event; } stage.mouseX = e.pageX - canvas.offsetLeft; stage.mouseY = e.pageY - canvas.offsetTop; }

 

Basically what I’m doing  above is determining a direction based upon how far left or how far right the mouse is positioned on the screen (Feel free to show me a better way to do this in the comments). This direction number will be either positive or negative.

In the onMouseMove function I am determining the mouseX and mouseY co-ordinates which I use in the tick function.

Once I have a direction setting I update the x position of all the images that are children of the stage. As I am doing this inside the tick loop this will give the effect of the images moving.

When we start the browser we should see that now as we move the mouse left and right the images move along with the mouse.

That’s as far as am going to go with this this demo for now, I might revisit it at a later stage to clean up the JavaScript and add some of the the other effects that are used by capitalFM.

Published by thebeebs

Thebeebs is a Canadian pop singer, songwriter, actor and HTML5 junkie. Throughout his rise to fame, Thebeebs has been nominated and awarded numerous accolades, winning Artist of the Year at the 2010 American Music Awards, and being nominated for Best New Artist and Best Pop Vocal Album at the 53rd Grammy Awards. Thebeebs is considered a teen idol, and has been subject to acclaim from fans, as well as criticism and controversy from matters concerning his popularity and image.

23 Comments So Far, what do you think?

  1. Pingback:HTML5 Blog on: Elijah Manor: Underbelly » Creating a picture gallery with HTML5 canvas | MiloRiano: Computers news, tips, guides...

  2. Pingback:Tweets that mention Underbelly » Creating a picture gallery with HTML5 canvas -- Topsy.com

  3. Pingback:Creating a picture gallery with HTML5 canvas

  4. Pingback:TWC9: Coding4Fun, DevLabs projects, XAMLQuery, VS Achievements | Pozitive.NeT

  5. Pingback:TWC9: Coding4Fun, DevLabs projects, XAMLQuery, VS Achievements | Website Under Construction

  6. Pingback:Weekly Links– 2010_06 | MS-Joe (Joe Stagner)

  7. Pingback:Underbelly » Border Radius and Capital FM

  8. Pingback:Underbelly » HTML5 and CSS3 demos

  9. Daniel White

    Looks pretty neat, will have to bookmark this for later. Thanks!

  10. Phil Snow

    Great use of the canvas.

    So now that this demo is a few months old, there are multiple releases of easeljs. Which version did you use for the demo?

  11. Ahmed

    nice article i liked it.

    is there a reference for image effect to create nice effect for the images,

    Thanks

  12. thebeebs

    @Phil I used version 1.0

  13. thebeebs

    @ahmed no sorry I didn’t write that up. Canvas pad shows you how you can create shadows and borders using the HTML5 Canvas tag http://ie.microsoft.com/testdrive/Graphics/CanvasPad/?c=shadows

  14. Ahmed

    thanks thebeebs,

    there is problem with mouse events, if i change the image source to URL, mouse events will not work. like: onPress with bitmap

    i posted the issue here:
    http://groups.google.com/group/easeljs/browse_thread/thread/c6ba630573276404/ffa38b67618fb7e2?lnk=gst&q=mouse+event#ffa38b67618fb7e2

  15. thebeebs

    @ahmed Thats an interesting problem. If you put an exmaple up on jsfiddle I can see if I can resolve it. Out of interest what browser are you using?

  16. Ahmed

    it is happen with chrome, firefox and ie.

    you can test the example DraAndDrop in the library and change the image source to any image with http.

    image to test: http://www.minihath.com/img/caption.png

    Thanks

  17. Andy

    Hi,
    thanks for a really interesting article, I have followed along with it and got quite far, however when I add the line : ‘stage.children[i].x = stage.children[i].x + direction;’

    The images no longer are positioned correctly, they are in the top left corner and in firebug I get the following error:

    stage.children[i] is undefined

    If I comment out that line the layout is back but obviously there is no animation…

    Many thanks

  18. Gus

    Nice guide! What editor are you using?

  19. Praveen

    Hi,

    Nice work.. I really appreciate. I want to add the click event of the images getting added in the canvas. But im not able to raise the click event. I was able to raise the mouse’s click event of the canvas but not individual images added into the canvas. Please help

  20. get4druck

    great stuff -> bookmark… very nice gallery function. But with older PC (like my work pc) its a hard thing and make it very slow.

  21. Menre

    I am doing this for real. I love this tutorial and would want to use it to complete my task. I was able to download EaselJS and add everything you said. I followed the tutorial well, but got stuck when I reached the area of:

    function imageLoaded() { imageCount++; if (imageCount >= pictures.length) { createBitMaps(); } }

    Could you help me with the completed file please so that I can get it right? I don’t understand where to put stuff anymore. Thanks

  22. Menre

    Alright, I have now been able to add the code correctly after watching your tutorial video. I noticed on your video that in the head section of your design page you also linked to a file called debug.js. You created a function called enableDebug() in the page section of your work, are these two things needed for the code to work? I am asking because after typing up the code as you did when I run my page nothing is displayed and I get the error message below.

    Message: Object doesn’t support this property or method
    Line: 68
    Char: 2
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/utils/SpriteSheetUtils.js

    Message: Object doesn’t support this property or method
    Line: 76
    Char: 1
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/display/DisplayObject.js

    Message: Object doesn’t support this property or method
    Line: 47
    Char: 3
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/display/DisplayObject.js

    Message: Object doesn’t support this property or method
    Line: 52
    Char: 3
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/display/Container.js

    Message: Object doesn’t support this property or method
    Line: 47
    Char: 3
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/display/DisplayObject.js

    Message: Object doesn’t support this property or method
    Line: 47
    Char: 3
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/display/DisplayObject.js

    Message: Object doesn’t support this property or method
    Line: 48
    Char: 3
    Code: 0
    URI: ../EaselJS_v0_3_2/src/easeljs/display/Stage.js

    I get a blank page though I have made a link to an image correctly. Any advice on how I can get it to work?
    Thanks

  23. Kamlesh

    Hi,

    Good Stuff. And also quite easy way to demonstrate. Actually I have a question, If I want to stop at the last of left and right when the image ends, how to do that.

    Cheers :)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>