The Technology Behind the Roundarch/OneRiot Web Application Designed to Feature IE9’s support of HTML5


Sept. 15th, 2010, Microsoft co-launched IE 9 and a companion site, ‘Beauty of the Web’, to feature projects written to take advantage of the new browser. Roundarch and OneRiot partnered to build an app featured on this site. Using OneRiot’s Trending Ad API, Roundarch conceived and developed, a concept site designed to feature IE 9’s support of HTML 5 standards and graphics acceleration.

In essence, we built an interface that allows users to interact with trending topics as balls in a tank. Data about the trending topic was used to draw the ball’s size and color. Balls can be tossed around the tank and possibly into a ‘follow’ or ‘ignore’ bin, as well as clicked on to bring forth a modal window displaying OneRiot content. Further, A timeline component allows the user to see changes to trending data between time intervals: data begins collecting for these intervals as soon as the user enters the site.

This project featured three essential technologies: Microsoft’s Azure cloud service for backend support, and HTML5 and the Box2d physics engine for the front end. This post goes into detail on our use of HTML5, and touches on the other technologies.


Our use of Azure consisted of two webservices. The first of these services, a ‘Worker Role,’ was written to regularly query the OneRiot API, parse and archive data on the top 50 trending topics. This data is stored in the cloud, and is used to service the timeline component of the site as well as provide current trending data to ball tank. The second service, a ‘Web and Worker Role,’ was created to serve the site.

HTML5 and Canvas Drawing

Drawing the physical interactions of bubbles in the site relied on the use of the HTML5’s canvas tag in conjunction with a javascript port of the Box2d physics engine. Javascript and jQuery were used for all front end programming – I’ll focus on how this was done for the majority of this post.

The canvas tag’s context property is used for all drawing operations. If you are familiar with AS3, the context behaves similarly to the .graphics property of a DisplayObject: the context can render drawing operations, like fills, strokes, and gradients, as well as manage alpha, render text, and perform pixel by pixel operations.

The canvas tag itself allows only three properties: id, width, and height. Any drawing that occurs outside the bounds of the canvas does not render.

Here’s a quick drawing example. In the following HTML document:



<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE-9"/>
    <title>Drawing a Red Square</title>
    <canvas id="myCanvasId" width="100" height="100"></canvas>
    <script src='redsquare.js'></script>

You could use the following script to draw a red, 50x50px square to the screen:



var canvasContext = document.getElementById('myCanvasId').getContext('2d');
canvasContext.fillStyle = "rgb(255, 0, 0)";
canvasContext.fillRect(0, 0, 50, 50);

To draw the ball tank, we implemented a loop that updates bubble position using a physics engine, allowing for realistic interactions between balls in the tank.

Before the drawing

Prior to the physics engine starting, an array of roughly 200 ball images are created. There are 9 basic colors to the balls in the tank plus 24 intermediate colors between each base color, used for tweens; a separate image is created for each base and intermediate color. This is done by creating a canvas for each image (which is not drawn to the screen), and using that canvas’ context to draw a gradient-filled ball with the current color. We also create a separate image that will be used to give each ball a specular-like highlight.

In the loop drawing

After these images are created, we start a loop that continuously draws the bubbles. The basic process for the loop is as follows:

1) Parse incoming trend data by comparing it against the current trends.

  • New objects are built for each new trending topic and added to the physics engine.
  • Topics in the engine but not in the new list are removed from the engine and a set of tweens are run on the object to visually transition it out.
  • Topics in the engine and the incoming list have their size and color properties updated and tweens started to animate these changes. Since updating the properties of an object active in the simulation proved too difficult to implement for launch, we suspend that object from interacting in the engine while it is being updated.

2) Step the physics engine forward, check for collisions. We use the engine’s collision detection to determine if a ball has been tossed into the “following” or “ignoring” bins. Start transition tweens on any ball that has been added to either, and remove that ball from the engine.

3) Clear the rendering context.

4) Render each ball. Step through every ball and transform the drawing context’s matrix to match the ball’s properties; x, y, rotation, scale and alpha. These properties are managed either by the physics engine or by tweens, depending on whether the ball is active in the engine. Balls not active in the engine are either transitioning out of the app or transforming based on new trend data.

Once we’ve transformed the context’s matrix, we look up the ball’s color index which tells us which image we will be drawing with. Use this image to draw the ball, then draw a highlight over this image. Next, we draw the trend’s title over the ball images. Finally, we reset the context’s transform matrix and move onto the next ball.

Here’s a little bit of pseudo-code to illustrate the loop. This simplifies the process, but gives you a rough idea:

// begin with an untransformed context matrix;
context.translate(x, y);
context.scale(scaleFactor, scaleFactor);
context.globalAlpha = .8;
context.drawImage(balls[colorIndex].canvas, -radius, -radius);
context.globalAlpha = 1.0;
context.drawImage(highlight.canvas, -radius, -radius);
context.fillText("My Trend", x, y);
// restore the untransformed matrix


There is a lot left out of the above code, but you can read more about the canvas tag and 2d context here to fill in the missing pieces. Look back here also for more posts about HTML5 and the canvas tag.

The timeline

The timeline at the top of the site, also drawn using a canvas, begins collecting and storing trend updates locally in the user’s browser as soon as the site is accessed and continues to collect data for a 24 hour span every 30 seconds. These intervals are marked by icons on the timeline.

Users can select any marked interval in their timeline, causing a trend update to occur. This affects the first portion of our drawing loop as explained above. Intervals clicked near to the current one may yield unnoticeable changes to the balls within the tank, while farther intervals can show dramatic changes to the size and color of each ball, especially in a busy news cycle.

Clicking on any hour prior to the first site access will cause the site to load a single trend update from the cloud for that hour.


The Box2d physics engine was used to calculate the physical interactions of the balls. Specifically, we used box2djs, a javascript port of the engine. Body and circle definitions were added to the engine for each ball, with UserData attached to each ball that contained necessary drawing information, either static or managed by a tween. For example, we stored a ball’s color index in the UserData.

The box2d engine if you are interested in exploring it further, and the javascript port we used is available .

We used code written by Mr. Doob to help get us working and understand how to translate the data from box2d into canvas coordinates.

More News

| 11th Dec 2018

What Marketers Can Learn From Burger King’s Geo-Conquesting Strategy Against McDonald’s

Who would've predicted that the physical space that your brand takes up could be up for grabs to competitors?

| 10th Dec 2018

Curriculums Aren’t Just for School Anymore

Selections from the CTO’s library and Isobar's core curriculum.

| 6th Dec 2018

The Move to Focused Markets

IGNITION 2018 - Day 2 Recap