Tuesday, November 15, 2011

NMA project update - drawing with images

I have been experimenting with how to draw and layout content - the image grid particularly. Here are a few of my iterations.

I was excited to try some html 5, so I dove right in and played with <canvas>. After figuring out how to get the canvas and make a context in it to draw to, I was able to layout the grid much as I would in Processing. As I ran through my loop of items I kept track of their x and y positions, and I could easily draw rectangles for items without images - canvas was intended for drawing.

Having smaller squares as place holders for items without images works pretty well to make the visualisation more compact and get more images (= interesting) on screen at once.

Object type sets drawn with an absolute position in a <canvas>

Working with canvas I even was able to make it scalable - by calling the draw function with both window.onload and window.onresize events, and then setting the canvas size to window.innerWidth and window.innerHeight.

However the problem with this approach is that everything that is drawn is not an html object, and therefore is static / can't be interacted with. In fact to have mouseclick or mouseover events would require separately keeping track off the mouse position, as you would in Processing. This is madness when html objects already have mouse interaction natively built in.

So next I went back to appending html using the JQuery $.append(string).  Here I threw back all the images with absolute position, set again by keeping track of x and y positions as I looped through the items. The images had a straight html link also.

Object type sets (items with images only) drawn with absolute position as html <img>

This was ok, but clearing the old images, running through all the date and recalculating x and y positions each time the window was resized made it slow and clunky (and only working with 800 of the 48,000 items). Also I was appending html after collecting it for an entire object type set - it would be nice (and easy) to append after looping past each item so that on a slow load you would be able to see the visualisation being populated.

A better way I quickly discovered was to use the document flow. The trick that had alluded me was an object display property 'inline-block', which allowed me to create objects (I started using the generic <div>) that had fixed dimensions and that followed one after another inline - ie all my earlier attempts with the document flow had resulted in each list item having a new line. One note - it appears, like canvas, to not be supported everywhere. To get this to work I had to upgrade to the lasted versions of Internet Explorer and Mozilla Firefox.

Object types sets drawn in the document flow as fixed dimension divs, inline-block

Looks good. The fixed dimension divs without images simply have a background colour. This actually is a very straight forward way to draw rectangles.

I still however had one small hiccup. The mouse interaction obviously doesn't happen at the same time that the html is being written in loop. I had to find a way to get the object to remember it's reference irn so that it could link to other stuff. I did this by writing at the time of the initial append, onclick to call a clickFunction with the particular irn already hardwired to pass in - ie onclick='clickFunction(" + item.irn + ")'.

An alert demonstrating that an item's reference irn can be recalled and that therefore interaction  is possible

I also made the object id be the irn so that it can be called from anywhere - this should allow me to highlight objects in the future! Apparently there is a convention for data attributes, ie storing data as a property rather than content - this seems counter intuitive, but perhaps it is a useful way to attach data but keep it hidden.

That's all for now.