A WebGL piece done for a client, this 3D photo directory was used as a showcase piece at a event in China, where this was shown on a gorgeous event screen the width of a banquet hall.

It was also designed for multi-browser, multi-form factor (desktops, mobiles) in mind, with end users being able to play with the piece on their devices, or on touchscreens.

The idea behind it was to allow participants to visually inspect all attendees of the event, and through filters and search be able to connect to and find information on people within their organization.

The 3D photo visualization piece that is linked is a sanitized demo version with randomly generated names and photos as the real piece has data that should not be shared publicly.

But the principles and ideas behind the piece still stands, and it might be interesting to go through some of the hurdles involved in building this piece of beautiful code art.

App features
This code art piece changed a lot along the way, from flat 2D photo planes that became cubes (because it fit in with the client’s event design theme).

Originally designed as a sort of a photo selfie mozaic, it morphed into a more useful visualization that could be easily updated and reused for next year.

Many modes were added along the way, like:

  • The base cube mode
  • The globe mode (which was designed to mimick the client’s circular logo – it has been changed in this version – and a bit of a “wow” factor during the presentation)
  • The showcase mode, which highlights a few important organization members
  • Gender sort, a way for organizing the data so that you can see the breakdown in the organization
  • Inspect mode, where you can type in a name and it will jump to that person
  • Filters like by profession and province, where you can see a selection of the data whilst the rest fades into the background

UX design
For each mode, care was taken such that when you transition between modes, there is some animation that gives a bit of a “wow” factor, as well as to cue to the user that the mode has been changed.

There are also various user interactions that allow users to interact with the visualization. This includes:

  • Zoom in/out using the mouse scroll (or for touch pinch in/out to zoom in/out)
  • Rotate left/right if you hold down the mouse button and draw across the screen (or for touch swipe left /swipe right)
  • When you start entering a name under inspect mode, it autocompletes all possible names that are available in the visualization, making it far easier to pick a name
  • When you click on any photo cube in any mode, it immediately jumps to that photo in inspect mode, letting you know who that person is.

Together with all the modes, sorts and filter functions, and by allowing the end user to search and photo inspect, the 3D viz allows users to explore the dataset in a fun and intuitive way.

Three.js: WebGL
The 3D portion of the piece is written in Three.js, one of the best well-known javascript libraries on 3D.

All the cubes are mesh objects located in 3D space, and their textures are the photos that have been mapped on 2 sides of the cube. We tried with more faces, but the amount of rendering involved was taxing on the piece, and 2 faces made for a more pleasing design.

The X, Y, and Z positions of the cubes are positioned using algorithms. For example, in the cube mode, a 10 x 10 x 10 addressing space was created and then randomly shuffled and packed with smaller cubes to give the idea of a packed cubic structure. Resting animations to make the cubes move and rotate were added to make the piece more interesting.

In the globe mode, the X, Y, and Z positions of the cubes were aligned according to circular cubic equations. For the filters, the photos are all arranged in squares of the filtered content (with a dynamic camera zoom based on the amount of people filtered).

Thus, when you switch between modes, you simply calculate the new cube positions based on the relevant equations, and then the transitions will occur.

Detecting if you could click a cube was based on raycasting collision detection with the camera. If the cube is hidden by another cube, you cannot click on that object.

Miscellaneous: libraries used
Hammer.js was my touch library of choice. Originally we used some of javascript’s native click and scroll functions, but they did not mimick as naturally the tap, swipe and pinch in/out functions on a touch screen. Hammer.js touch functions proved to feel more natural and was thus used in the final piece.

SVG and HTML animations for the piece was done using Greensock, my go-to library for animations. From the pop-up information displays, to the sidebar animations, these were done using Greensock.

For the real piece, because we read from a CSV data backend, I used papaparse.js to parse the data into JSON chunks to populate the viz. For this sanitized version, chance.js was the library of choice to generate the random names and data.

And lastly, to round off everything, JQuery and Underscore.js were used. Both of these popular libraries have very useful functions, from DOM manipulation to sorting/filtering.

We investigated the use of other libraries like a load library, but Three.js very basic load manager proved sufficient for the piece, so no load library needed. Phew!

Miscellaneous: challenges
Because of how browsers’ canvas renderer draws animation frames, whenever the focus of the page is lost (i.e. you switch to another app or tab), the animation frames are not updated and are “paused”. This became an issue because in the animation, the X, Y and Z coordinates of the cubes are still being updated even though the frames are not drawn. Thus, when you switch back to the piece, cubes being in the wrong position is very common.

The fix was a solution based on the clock timer. On detection of defocus, start a timer. When you get back to the piece, detect how much time has elapsed, then repaint the scene based on where the cubes are supposed to be.

Other interesting challenges were due to browser specific issues, especially for mobile. The touch functions required quite a bit of debugging to make sure they work decently with the piece.

All in all, I loved doing a code art piece as pleasing and beautiful as this!


When you look back at the things that happen in a year, lots of things change.

Especially when you’re running a small SMB.

More connections. More clients. More projects.

V/R does quality interactive work for a living, and we thought that since we spend lots of time doing pretty stuff for clients, we should do the same for our own website.

And thus, when we have some time in between gigs we constantly write and rewrite old code, and our website is no exception.

It’s good to let potential clients know the range of interactive work we do – a blend of UX, web and app dev.

This marks the third year that we’ve changed our website, and this time the site is built from the bottom up from scratch.

It uses a lot of the techniques we’ve picked up in the last two years: SVG and canvas animations, visualizations (using D3), scroll-based animations (ScrollMagic as a base with GreenSock). There is a lot of javascript code we wrote and packaged together to get this look and feel.

Because it is our own site, we get to experiment with things that we want to try, like for example the procedurally generated parallax layers in the background (visible only on desktops mainly). This is pretty cool, but testing this with responsive layouts was so heavy that we decided to take this out for mobile/tablets.

Other examples include our own project picker/visualizer instead of using a popular library like Isotope.js (like our previous website). I wanted a 3D animated version with a rotating menu that had to be extensible and responsive, so we had to write our own.

Smooth SVG animations hooked to a scroll based mechanic (as opposed to animated gifs or videos). A canvas-based projected spinning globe (based on real geojson dataset!) rather than a flat globe image.

And because a lot of these SVG animations have a light size footprint, they load quite fast, and are reasonably sharp at any size, which is good fit for the new design. Here’s a good post by Sara Soueidan on SVG animations vs animated GIFs.

I often get asked this question by marketers: What is the reach of the work that you do? How many people see your content and what are the KPIs?

The answer is that for many of our clients I don’t know. Whilst we might help them install their analytic tracking code snippets, short of installing our own code (which we don’t do), only the client will know after we hand over the project code for them to host.

However, for the projects that we do for our own interest, development and showcase — e.g. the Visualizing Singapore site — we have a sense of how well they do. I am a firm believer in tracking and measurement; if you don’t track, you don’t know who is going to your website and what content they are looking at.

For example, the last SG elections website was a big hit during the elections weekend of 11th to 12th September as we were updating the elections results live on 11th evening / 12th morning.

Literally you could see the voting districts being filled in with colour and numbers as the voting results came in, both the sample vote results and also the real election results.

Specifically for the 24 hours from Friday evening to Saturday evening post results, we received almost 200,000 page views, mainly from our live embeds, which were on both the Online Citizen and the Middleground.

A big shoutout to them for covering the elections with such great content.


Google analytics statistics of the SG Elections website. The statistics here were from 11th to 14th September, but the bulk of the hits were during 11th and 12th.

Most of the traffic came from the embeds, specifically our vote share visualization which was embedded the most by TOC and TMG. Some came to the SG Elections website, mainly through word of mouth referred by social media and also by very kind shoutouts by our media partners.

I didn’t pay a single cent for social media advertising of any sort, and whilst I may have made a few posts on FB and Twitter, I didn’t spam my channels too much. I had a hope that with great content, and perhaps media who might be interested in the free easy-to-embed content (just attribute to us), that would be enough. The site wasn’t really marketed.

Page views aside, what I was most happy about was the engagement. An average of 3mins plus for the vote share visualization, and 6mins plus for our actual site — a rarity in an age where people move on very quickly.

I suspect it is folks just leaving the page open as the elections maps were being updated in real-time. Still, am humbled and happy that people found the visualizations useful, which was what Kok Keong and I wanted to do in the first place.

A quick word to those new to us. We’re not media, we don’t compete with media. We’re also not a marketing, PR, or even traditional creative/digital/social media agency (which in fact we do some work for agencies behind the scenes).

We’re a UX design outfit that uses data science and digital perspectives to present stories and insights in a better way.


The latest version of SG elections is up at

In addition to the original GE2011 data, the elector, map and candidate data have now been added for GE2015. There is also a new chloropleth map on where the opposition is contesting.

There has also been significant redesign of the UI and layout, especially the tables in how the information is presented.

This aligned with our goal of making the site more responsive, and the layout is cleaner for both desktops (you probably don’t need to scroll anymore to see all the details) and mobiles/tablets (It fits a vertical view better).

Making the piece responsive was a pain to write — had to make sure it mostly works on all the browsers and various form factors (mobile / tablet / desktop).

Lastly, we added in some bling factor with cool animations and transitions. Kok Keong did an absolutely amazing job with the year transitions and the change in districts!

Embedding chloropleth maps for GE2015

In addition to the above, we also created responsive embeddable election charts for any blog or media who wants to embed them! All we ask for is just to attribute back to either V/R or Thanks!

The five charts are listed below, with sample iFrame code that you can just copy and paste and it should work.

Seats and Candidates:

<div style="position: relative; padding-bottom: 70%; height: 0; overflow: hidden;"><iframe src="" style="position: absolute; top:0; left: 0; width: 100%; height: 100%;" frameborder="0" scrolling="no"></iframe></div>

Opposition Parties:

<div style="position: relative; padding-bottom: 70%; height: 0; overflow: hidden;"><iframe src="" style="position: absolute; top:0; left: 0; width: 100%; height: 100%;" frameborder="0" scrolling="no"></iframe></div>

The following charts are not populated yet because the election data is not in yet. We will update it live during the elections on 11th September 2015, which will colour the map. The following embeds are designed to self-refresh after 5 mins.

Stick them on your blog page and it will refresh live during the election on 11th September!

Vote Share:

<div style="position: relative; padding-bottom: 70%; height: 0; overflow: hidden;"><iframe src="" style="position: absolute; top:0; left: 0; width: 100%; height: 100%;" frameborder="0" scrolling="no"></iframe></div>


<div style="position: relative; padding-bottom: 70%; height: 0; overflow: hidden;"><iframe src="" style="position: absolute; top:0; left: 0; width: 100%; height: 100%;" frameborder="0" scrolling="no"></iframe></div>

Spoiled votes:

<div style="position: relative; padding-bottom: 70%; height: 0; overflow: hidden;"><iframe src="" style="position: absolute; top:0; left: 0; width: 100%; height: 100%;" frameborder="0" scrolling="no"></iframe></div>


An interesting project for BCN Global.

Besides doing the responsive bootstrap website design for them, the more interesting portion was helping them to come up with a real-time data visualization.

As you fill up their survey (done in SurveyGizmo), the data is pulled from their API to our database to be visualized in a cool and interesting way.

In doing this project, I learnt a few things.

It shows that visualization can not only be used for marketing needs, it can also be used to mine business insights and be used as a data product to be potentially sold to customers.

It requires the far-sighted boss or individual to see the potential of what such UX technology can do, and kudos to my client for this!