Hi, I'm Ben. This is my blog. I write about Flex,
Flash, software development, and other miscellany.

Custom Grids and Axes in Flare

As I mentioned in my last post, I have begun a project using the Flare data visualization toolkit, and I intend to document things I learn along the way. One of the first things I investigated, after familiarizing myself with the basics was how customizable the grids and axes for visualizations could be. It took me longer than I expected to figure things out, but now that I have I would say the grids and axes in Flare are highly customizable, and should be capable of accommodating just about any needs you may have.

This post is mostly code and images, but in case you want to jump around here is a table of contents.

Background info

Before we dive in to the examples, I need to cover a tiny bit of background information and establish some constants we'll be using. First, all of the examples will be using this simple data source:

// source data
private var arr:Array = [
                        { x: 2, y: 2 },
                        { x: 4, y: 4 },
                        { x: 6, y: 6 }
                        ];

As you can see, its just an array containing 3 elements who each have an x and y property. Next, we'll look at a bare bones plot chart built with Flare. The following is essentially the bare minimum of code required to create a visualization in Flare. The default visualization is a plot chart using circular shape renderers, which is fine for our purposes here. We'll be using this code as a basis for the code added/demonstrated through the rest of the post, but I won't be repeating it all every time. Lastly, remember that Flare visualizations are really just Sprites, which means they cannot be added directly to Flex containers, only to DisplayObjectContainers, which is also Sprite's super class. UIComponent, and therefore most every Flex component, are in fact descendants of Sprite, meaning you can add Sprites to UIComponents. For more information on Flash Player's core display classes, see this page.

Base code and a basic grid
// visualization (Flare's core element)
// use Flare's Data class to convert
// our Array into a format it can use
vis = new Visualization( Data.fromArray( arr ) );

// fill the UIComponent that will be our parent
// this is a Flex app, so assume uic looks like this
// <mx:UIComponent id="uic" width="400" height="300" />
vis.bounds = new Rectangle( 0, 0, uic.width, uic.height );

// create an axis layout (Cartesian chart)
// instruct the layout/grid to use the x and y properties
// of our data elements for plotting
var axisLayout:AxisLayout = new AxisLayout( "data.x", "data.y" );
// add it to the visualization's operators collection
// (operators will be discussed in a future post)
vis.operators.add( axisLayout );

// update the vis
// (make it process and apply any pending changes)
vis.update();

// add it to the display list as a child of our UIComponent
uic.addChild( vis );

This code produces the following visualization:

Default Flare grid

As you can see, the grid bounds are dynamically created based on the data being shown. This would be very convenient if that is what we wanted, but in my case it was not.

Controlling grid bounds

If we'd like the chart's minimum values to always be zero, we can use the zeroBased property of the xScale and/or yScale properties of our axisLayout. The following code will cause both the x and y axis to begin at zero.

axisLayout.xScale.zeroBased = true;
axisLayout.yScale.zeroBased = true;

To control the maximum values of our chart we can use the preferredMax property.

axisLayout.xScale.preferredMax = 10;
axisLayout.yScale.preferredMax = 10;

Note that there is a preferredMin property as well, but it (oddly) is ignored when set to zero. You can use it to set the lower bounds of your axes to any value other than zero. Adding the two snippets above has specified that our chart axes should begin at zero and end at 10, regardless of the data being shown. The resulting chart looks like this:

Custom axis bounds
Customizing grids and axes

To really start customizing your chart, you'll want to use the xyAxes property of Flare's Visualization class. xyAxes is of type CartesianAxes and contains several convenient properties, as well as providing access to xAxis and yAxis properties that represent exactly what their names say, and are both of type Axis.

Maybe you want to eliminate the default grid pattern in favor of a simple bottom and left border.

// effectively only hides top and right borders
vis.xyAxes.showBorder = false;
// show bottom border
vis.xyAxes.showXLine = true;
// show left border
vis.xyAxes.showYLine = true;
// hide vertical grid lines (along x axis)
vis.xyAxes.xAxis.showLines = false;
// hide horizontal grid lines (along y axis)
vis.xyAxes.yAxis.showLines = false;

flaregrid_03

The xAxis and yAxis elements also provide some useful properties that we can use to further customize our chart.

vis.xyAxes.showBorder = false;
vis.xyAxes.showXLine = true;
vis.xyAxes.showYLine = true;

// distance beyond left edge of axis
vis.xyAxes.yAxis.lineCapX1 = 20;
// distance beyond right edge of axis
vis.xyAxes.yAxis.lineCapX2 = -(vis.xyAxes.layoutBounds.width);
// distance to move labels
vis.xyAxes.yAxis.labelOffsetX = -25;

// distance beyond bottom edge of axis
vis.xyAxes.xAxis.lineCapY1 = 15;
// distance beyond top edge of axis
vis.xyAxes.xAxis.lineCapY2 = -(vis.xyAxes.layoutBounds.height);
// distance to move labels
vis.xyAxes.xAxis.labelOffsetY = 20;

This code produces the following chart:

flaregrid_04

Useful methods

There is also an axisScale property on the Axis class (our xAxis and yAxis elements). axisScale is typed as Scale, but will usually be a ScaleBinding instance as Scale is essentially an abstract class. Scale (or rather its subclasses) provide two very useful methods, interpolate( value:Object ):Number and lookup( f:Number ):Object. The interpolate method will return a number representing where on the scale the passed in value falls. In our example where our range is 0 to 10, 5 would return .5, 8 would return .8, etc. The lookup method essentially does the opposite, accepting a number and returning the corresponding value on the scale, meaning .5 would return 5 in our example, 2 would return 20, and so on. These methods can be extremely helpful if you need to do custom drawing on your chart, and are the kind of value translation methods that seem to be missing from the Flex charts.

Conclusion

This is obviously not an exhaustive list of customizations possible with Flare, but it hopefully gives you an idea of the kinds of things you can do out of the box. I haven't decided which topic to cover next, so if there are specific questions or features people would like to see let me know in the comments.

Digging into Flare

If you haven't heard of Flare, go check out the demo right now. I'll wait.

Pretty cool, eh? Flare is an ActionScript port of Prefuse, a "set of software tools for creating rich interactive data visualizations" written in Java. The development of both Prefuse and Flare were led by Jeff Heer, I believe as part of his Master's thesis. I have recently begun to investigate Flare as a potential replacement for Flex charts in my current project at work and have been lucky enough to spend the past two weeks simply diving in and learning how to use the library. I needed to determine whether or not, and how easily, we can do everything we hope to on this project. My conclusion is that Flare is extremely powerful and will almost certainly support any kind of visualization we can think up.

That being said, our project is a Flex application, and Flare is simply an ActionScript library. It has a very basic wrapper component (FlareVis) that extends Flex's Canvas component, which allows basic instantiation and configuration in MXML but the library is not especially Flex-friendly. My plan is to create some wrapper APIs and higher level classes that will make using Flare in Flex much easier. What is even cooler is that our awesome client has expressed their desire for these enhancements to be contributed back to the community so that others may benefit. There is a lot of work to be done but I am really excited to start making progress. For example, Flare doesn't have specific components like a Bubble Chart, you simply have a base Visualization class that you customize and extend to create what you need. Developing with Flare has reminded me of my old AS2 days because of its dynamic qualities and freedom from the constraints the Flex framework places on you. (Note I am certainly not knocking Flex; its how I make my living and the only kind of serious AS3 work I have ever done.)

Flare works with lower level classes than you normally would in Flex, with Sprite being the core display class. This is undoubtedly one of the reasons you can attain such amazing performance with Flare. During one of my tests I animated 2000 bubbles on a chart with no noticeable slowdown or degradation, which I don't think would be the case on a Flex chart. In case you are not aware, Sprites are like single frame MovieClips in Flash. They do not have an internal timeline, but they are a direct extension of DisplayObjectContainer, meaning they can contain child objects. They of course also have a graphics property that allows you to use the drawing API to customize their appearance. They are not UIComponents, so you cannot add them directly to containers in Flex, but that is not a big deal. You can add them as a child of a UIComponent instance, and then add the UIComponent to a container like usual.

That is probably enough introduction and rambling for now, but you can expect a steady stream of posts from me about various aspects of Flare, further experiments and progress on the wrapper APIs. For more frequent and less formal updates, you should follow me on Twitter here.