Axiis Tech Demo: Visualizing Historic Browser Statistics

For the beta release of Axiis I prepared a visualization showing the historical browser breakdown of visitors to W3schools.com.  I wouldn’t consider it a useful data visualization by any stretch of the imagination (pie charts are not a great idea, and concentric pie charts… oh my!), but it does demonstrate how easy it is to get started with Axiis and build something complex in a few lines of mark-up. Since the beta release I added the ability to filter by browser type, and Tom lent his artistic eye and did a little restyling.  Although the number of Axiis tutorials out there is growing steadily, there are still very few, so I’ll dive deep and explain exactly how this visualization works.  Check it out here.

What am I looking at exactly?

Each of the concentric rings are essentially pie charts showing the percentage of visitors using each browser for a particular time slice, starting with January 2002 in the center and working out to August 2009.  The numbers on W3schools.com don’t quite add up to 100% because they don’t report on browsers that make up less than 0.5% of their visitors.  This results in a gap at the end of each ring.

How’s it done?

This only took a few hours to construct, and the most time consuming part was parsing the data.  The HTML from W3schools wasn’t valid XHTML, so I couldn’t tear through it using AS3′s E4X parsing without doing some manual manipulation beforehand.  When all was said and done, I ended up formatting the data as XML with a series of “month” elements with “browser” children that detailed the share of each browser for the corresponding time period.  None of the parsing involved any of the Axiis framework — just a few loops and conditionals.

<data>
  <month value="August 2009">
    <browser name="IE7" share="0.151" month="August 2009"/>
    <browser name="IE6" share="0.136" month="August 2009"/>
    <browser name="IE8" share="0.106" month="August 2009"/>
    <browser name="Firefox" share="0.474" month="August 2009"/>
    <browser name="Chrome" share="0.07" month="August 2009"/>
    <browser name="Safari" share="0.033" month="August 2009"/>
    <browser name="Opera" share="0.021" month="August 2009"/>
  </month>
...

Conceptually, there are two parts to the browser visualization: the concentric time slice rings and the wedges that divide the time slices down by browser.  To create this effect, I used Axiis’s embedded layouts.  Layouts loop over a given data provider, manipulate Degrafa geometry based on that data, and draw to the screen.  Layouts can be nested inside on another and behave analogously to nested loops in the programming world; for each iteration of an outer layout, the inner one will loop over all of its data, performing its expected tasks.

The outer layout

<axiis:DataCanvas id="dc"
	width="100%"
	bottom="20"
	top="120">
	<axiis:layouts>
		<axiis:ConcentricWedgeLayout id="radialLayout"
			width="{dc.width}"
			height="{dc.height - 10}"
			innerRadius="52">
...

When the application is done going through its creation process, an event handler is called which parses the XML and passes the resulting ArrayCollection of month Objects to the outer layout, which is an instance of ConcentricWedgeLayout. This type of layout manipulates the inner and outer radii of a Degrafa Wedge such that the during the course of the loop the Wedge will have taken on all the values necessary to fill the space available.  After each iteration, the Wedge and the browser Objects that belong to the current month are passed to the inner layout.

The inner layout

The inner layout was custom-built for this visualization.  It leverages some of the events fired during the layout’s render cycle to adjust the angle of the wedge. The preRender event is fired at the very beginning of the layout’s render cycle, before a single iteration has happened.  During preRender, the currentArc property is set to 0.  This makes sure we’re always starting from the 12:00 position on the visualization.  Since this layout has drawingGeometries defined, the layout dispatches the itemPreDraw event right before drawing them to the screen.  In this example, the itemPreDraw handler updates currentArc to the appropriate value to show the percentage for the browser the layout is currently holding.

<axiis:LinearScale id="arcScale"
	minValue="0"
	maxValue="1"
	minLayout="0"
	maxLayout="359.99"/>
...
<axiis:BaseLayout id="arcLayout"
	dataProvider="{radialLayout.currentDatum.browser}"
	preRender="{currentArc = 0}"
	itemPreDraw="{currentArc += arcScale.valueToLayout(arcLayout.currentDatum.share);}"
...>

Note the use of the LinearScale here.  The Axiis scale classes create a mapping between two data spaces that we call “value” and “layout”.  In this example a linear mapping is created between the range of possible percentages (0 – 1) and the range of possible angles (0 – 359.99). The valueToLayout method does exactly what you’d expect it to.  Given a number from the value space, it will return a corresponding number in the layout space.  This is used to advance the reference Wedge’s angle by the appropriate amount.

Drawing to the screen

Aside from manipulating the angle of the reference Wedge, the inner layout is also responsible for rendering a Wedge to the screen.  The reference Wedge and the drawing Wedge are two separate instances, but the latter derives its properties from the former.

<geometry:Wedge id="wedge"
	centerX="{radialLayout.width/2}"
	centerY="{radialLayout.height/2}"
	innerRadius="{radialLayout.currentReference['innerRadius']}"
	outerRadius="{radialLayout.currentReference['outerRadius']}"
	startAngle="{270 + currentArc - arcScale.valueToLayout(arcLayout.currentDatum.share)}"
	arc="{arcScale.valueToLayout(arcLayout.currentDatum.share)}">
...
</geometry:Wedge>

A mapping of browser names to colors defined at the top of the application is used to determine the fill and stroke applied to the Wedge.

<geometry:fill>
	<degrafa:SolidFill id="wedgeFill"
		color="{browserColors[arcLayout.currentDatum.name]}"/>
</geometry:fill>
<geometry:stroke>
	<degrafa:SolidStroke id="wedgeStroke"
		color="{ColorUtil.adjustBrightness(browserColors[arcLayout.currentDatum.name],-60)}"
		pixelHinting="true"
		alpha=".7"
		weight=".5"/>
</geometry:stroke>

Making  it interactive – States

Axiis states are conceptually similar to Flex’s states; they define alternative properties for the rendered geometries based on certain conditions. When the user interacts with a rendered geometry, some familiar events are dispatched (mouseOver, mouseOut, etc.).  The layouts capture each of these events and if there are any states registered with the event type in question, the state is applied.  This declaration says that when the mouse is over a wedge the wedgeFill should have its color property dimmed and this action should be undone when the mouse is moved off.

<axiis:State enterStateEvent="mouseOver"
	exitStateEvent="mouseOut"
	targets="{[wedgeFill]}"
	properties="{['color']}"
	values="{[ColorUtil.adjustBrightness(int(wedgeStroke.color),-60)]}"/>

The filtering legend

If you followed how the layout routine works in the main visualization, the construction of the legend is a no-brainer.  It’s a VBoxLayout — a layout which spaces out RegularRectangles across its available height — and it draws a colored square and some text to the screen for each browser name.

<axiis:DataCanvas id="legendDC"
	width="200"
	height="{legendLayout.itemCount * 18}"
	bottom="5"
	left="5">
	<axiis:layouts>
		<axiis:VBoxLayout id="legendLayout"
			width="{legendDC.width}"
			height="{legendDC.height}"
			showDataTips="false"
			itemClick="legendLayout_itemClickHandler(event)">
			<axiis:drawingGeometries>
				...
			</axiis:drawingGeometries>
			<axiis:states>
				<axiis:State enterStateEvent="selected"
					exitStateEvent="unselected"
					targets="{[legendMarkerFill,legendLabel]}"
					properties="{['alpha','italic']}"
					values="{[.1,true]}"/>
			</axiis:states>
		</axiis:VBoxLayout>
	</axiis:layouts>
</axiis:DataCanvas>

The visualization allows the user to click on items in the legend to filter out the corresponding browsers.  To do this, there is an handler set up on itemClick event on the legend layout.  itemClick is dispatched when a rendered geometry belonging to the layout is clicked.  The event handler updates the list of browsers to include.  In the declaration for the inner layout on the main visualization, a dataFilterFunction is defined which checks the current browser’s name against the list of included browsers.  Any browsers that fail this test (i.e. the filter function return false) are skipped by the layout.

The state defined on the legend uses two custom event types, “selected” and “unselected”.  The “selected” event is dispatched when a rendered geometry is clicked and the “unselected” event is dispatched when that same geometry is clicked again.  In the selected state the text becomes italicized and the fill for the legend marker becomes more transparent, indicating that the browser has been filtered out.

The filtering feature take advantage of a bug fix that was made after the release of the beta that caused problems when all of the data items were filtered from a layout.  The swc included in the view-source download is compiled from Axiis’s development branch.  We use our repository in a slightly non-traditional manner.  The trunk contains our latest release and our “development” branch contain the latest check-in.  Although the development branch is more or less stable keep in mind that it is where we work out new features, so it may not be completely polished and bug-free.  If you run into any bugs or need help with something, give us a holler on our google group.  Enjoy!

This entry was posted in Axiis, Flex, Information Visualization. Bookmark the permalink. Both comments and trackbacks are currently closed.

13 Comments

  1. Posted November 2, 2009 at 12:37 pm | Permalink

    Very great graph!

    First of all, excuse my ugly english…

    It seems like a trunk’s section, where anyone can see the yearly growth of that tree. The amount of users with Internet connection can be an analogy to this metaphor.

    In this way, how could we build each monthly section’s width using the growing amount users connected to Internet? It could give a visual perspective on growing number of users, and afford a realistic perspective to the percentual values.

  2. Posted November 2, 2009 at 11:14 pm | Permalink

    Hi Mario,
    I hadn’t noticed how similar the visualization is to the rings of tree before! I could definitely see making a similar visual for internet penetration. If the data is divided into time slices and then broken down further by type of connection (phone modem, cable, T1,…) you could swap that in for the data object in the application and everything should more or less just work. If you put something like that together, I’d be curious the see the results.

  3. Kevin
    Posted November 26, 2009 at 3:24 pm | Permalink

    Great work Michael, thanks for sharing your work and demonstrating the power of the Axiis framework!

  4. Posted January 6, 2010 at 7:20 am | Permalink

    Hi Michael,

    I’ve got to remix your data with other data sources, building your original graph with their rings with proportional width to the internet user’s growth.

    Dispite the next few days I’ll post the whole of the process in my blog (linking to your blog and Axiis site, of course), I’d like to send you a screenshot with the final result, and maybe the SWF file (or XML/MXML data). If so, could you send me an email to get in contact?

    Hope you’ll like it!

  5. Posted January 14, 2010 at 11:29 am | Permalink

    Was this intended to look like the Firefox icon?

  6. Yakup
    Posted January 21, 2010 at 11:39 am | Permalink

    @Dave: I think vice versa. Firefox was meant to create such a visual.

  7. Posted January 23, 2010 at 1:45 pm | Permalink

    Nice graphics and very informative.
    Thanks

  8. gnashy
    Posted January 26, 2010 at 8:46 pm | Permalink

    This flash-page doesn’t with nither gnash nor swfdec.
    this sucks
    why don’t you just use svg or png.

  9. Posted January 26, 2010 at 9:18 pm | Permalink

    Great work, thanks for demonstrating the power of the Axiis framework..
    very informative!!

  10. GB
    Posted February 5, 2010 at 8:25 pm | Permalink

    While this looks “cool” it only allows for a easy comparison across the first two segments, IE6 and IE7. After that, it’s nearly impossible to visually compare slices, because their baselines are offset due to the border between IE6 and IE7.

    Also, I’m not sure why the tail end of the bars (if you read them clockwise) are not evenly staggered. Do they not each represent a year, thus should all have the same length?

  11. Dave
    Posted September 14, 2010 at 6:47 pm | Permalink

    This is the first site where I noticed that IE8 isn’t really pushing IE6 out, but rather IE7. I guess there are two reasons. It’s easy for users to upgrade from 7 to 8, and IE6 continues to exist as long as corporations don’t upgrade their platforms from 2000. A beautiful piece of art. Thanks.

  12. Mark
    Posted October 5, 2011 at 9:31 pm | Permalink

    Is the XML data available? It would be interesting to update the chart with the most recent three years of data to see the ascent of Chrome, leveling off of Firefox and decline of MSIE.

    Thank you.

  13. Mark
    Posted October 5, 2011 at 9:36 pm | Permalink

    Found it in the srcview; thanks!

11 Trackbacks