Dynamic image collage with HTML5 and Canvas
In the last couple of months the hype around web technology has really started to heat up. The HTML5 standard is getting a lot of attention from all major browser manufacturers and all my favorite browsers are starting to support all the nice new features coming in HTML5.
One of my favorite new features is Canvas, prime reason being my hope to finally make Flash obsolete, sorry Adobe. Because I wanted to check out the capabilities of Canvas, I decided to start coding some simple projects with Canvas.
My first demo is a simple Canvas element which can be used to make a collage of images. The demo can be found here., you will need a Canvas compatible browser.
What does it do
The demo lets you search for images from Flickr. When you have searched for some images, you can click any of the images there to add them to the Canvas part of the page. When the image is added to the Canvas then it’s automatically created as a new layer. Each layer can be manipulated in the following ways: move, scale, rotate, move layer up and down, remove layer, change opacity, change blending mode and enable or disable shadow.
The layout is a bit similar to image edit software, which I think is quite simple to understand. The code might still contain some bugs and do some unexpected things. Rotating images and then scaling makes the whole thing kinda whobly!
How does it work
The JavaScript code for this demo is split up into two parts. The first is a library that loads in all the proper calls for the Canvas element and that gives the page the ability to modify the layers in the collage. The second part of the JavaScript code, is the code to handle all the page interaction and to bind the HTML controls for the layers. I won’t go into the code for the user controls. But the canvas control might be interesting:
jCollage = new Collage("#collage"); //Create new collage Object with id of the Canvas tag jCollage.setBackgroundColor("#fff"); //Set background color of collage jCollage.setBackgroundImage(img); //Set background image for the collage jCollage.redraw(); //Force redraw the collage jCollage.addLayer(img); //Add a new layer to the collage jCollage.getLayer(id); //Get layer by id jCollage.getLayers(); //Get Array if all layers jCollage.removeLayer(id); //Remove layer based on id jCollage.moveLayerUp(id); //Move layer up in the array jCollage.moveLayerDown(id); //Move layer down in the array layer.isVisible(); //Is layer visible layer.toggleVisible(); //Toggle visibility layer.hasShadow(); //Does layer have shadow layer.toggleShadow(); //Toggle shadow layer.setShadow(boolean); //Set shadow layer.getOpacity(); //Get opacity of layer layer.setOpacity(float); //Set opacity of layer layer.getCompositeOperation(); //Set the composite operation layer.setCompositeOperation(string); //Get the composite operation
You can find the JavaScript code for this here. I might one day work this out as a jQuery plugin, but don’t know if that will be worth the extra effort.
Conclusion
Getting up to speed on the Canvas element is quite easy and the information for the HTML5 standard is already enough to get you going. Because a lot of people have already been working with this feature, it’s also very simple to find more detailed information about problems and how to solve them.
The most difficult thing to get going was handling the collision interaction with the Objects, because I couldn’t use the normal mouse events based on the DOM. I had to figure out the math behind the collisions myself, this code is not very pretty. But after getting this demo running, I have to say that it was not very difficult to code and Canvas is definitely going into a direction were it could replace Flash functionality. I just hope that Internet Explorer starts supporting it some time soon as well!


Hi Berry de Vos,
My name is Sebastian and I’m currently working on a class project with three other students. We are making a collaborative visual space where users can create online collages in “plot” spaces near other users.
We are very thankful for your demo app and have been hacking away at it for the past few weeks (you can check our Google Code repository in the website link).
Currently, we are placing buttons for layer rotate, layer up, and layer down on the actual images themselves.
Within the Square function, I’m having some trouble comprehending the math in this.Rotate.
I know there are four points in every Square, so I’m thus trying to add a fifth point named rotateLocation (where the button will be):
this.a = a;
…
this.newX = this.c.x – (buttonSize * 3) – (buttonPadding * 3);
this.rotateLocation = new Vector( this.newX, this.c.y);
But graphically, this is not showing up directly to the left of point c, but actually to the left and below point c.
Could you provide me some basic overview of how this section of the code works, or point me to a link of reference?
Thanks,
Seb
Great work. I’m a flash developer and I’ve been playing around with doing something similar just to find how much of a “flash-killer” this html5 really is. I would say that it’s not there yet, but I have been pretty impressed with what you can do with it, and making the transition to javascript after coding AS3 is a pretty quick and painless one.
The one thing I don’t like is how sometimes the screen highlights (in blue), just like it would if you were highlighting text on a page. This happens sometimes on a lot of drag and drop features.
Is there anyway to turn this off?
This post was mentioned on Facebook by Richard Hawkesford.
I save and try to execute this demo in my web server,and it gets me an error “this.origin is null” ,there is anything that may have left?
The example you’ve got there looks awesome!
I like your blog
Came across your blog in Bing
I’ll Digg this, thanks!
Enjoyed the post
Found your blog through Google
Hey, thanks for this!
Just wanted to say thanks for this
Came across this on StumbleUpon
Hey, I just wanted to drop a note and say nice post!
Well I have been hacking on your example code for a week now. Your code is a fantastic starting point for learning how to use the canvas element. Thank you, thank you, thank you!
Thanks for posting this! I have just started to look at your code. A couple of things just popped out at me.
function centerSquareOrigin(a, b, c, d) contains 3 return statements, one returns a Vector, one returns null, and one returns nothing. Is this what you really want?
In your function square(a, b,c, d), in the rotate(angle) function,
are not aAngle and cAngle the same?
are not bBangle and dAngle the same?
Once you have calculated aAngle and bAngle, could you not just assign them to cAngle, and dAngle respectively?
Beyond that, do you need to calculate more than one angle? Once you compute the new [x,y] coordinates of the upper left corner, could you not just compute the new [x,y] coordinates of the other 3 corners using the delta-x and delta-y offsets computed from the old [x,y] and new [x,y] coordinates of just that one corner?
works great in FF3.5 on OSX, nice demo
Canvas isn’t supported in IE8, there is an extention plugin that I can use on my webpage to support some of the features. But because I don’t have IE on my computer I have no way to test this. Sorry about that, hope that MS starts supporting Canvas in IE9!
Hello, i having problems with the demo on Internet Explorer 8? do i need some plugin to view it_ thank you