Flare timeline series final result

Demo here. I’ve noted that the framerate is much better when the shockwave is included in a proper document, as opposed to the standalone swf I just linked to.


Full source code.

In my opinion I’ve now solved the lack of clarity in the prior attempts we went through in the prior article in this series, so there will be no need for jqPlot or jFlot, or any other canvas based solution for that matter. The following has been added with the help of my own inference and a lot of copy pasting from various demo apps:

1.) The ability to selectively display plots by clicking their legends.

2.) The ability to turn a fish eye distortion on as a tool that can further help with examining the data.

3.) A tool tip box that will constantly display the current date and word count where the mouse pointer hovers.

Let’s take a look at the needed code for each one, starting with 1.):

new ClickControl(LegendItem, 1, function(e:SelectionEvent):void {
	if(_shown.length == 0)
		_legend.setItemProperties({alpha:0.5});
		
	var word_num = words.indexOf(LegendItem(e.object).text);
	if(_shown.indexOf(word_num) == -1){
		_shown.push(word_num);
		e.object.alpha = 1;
	}else{
		_shown = _shown.filter(function(element:*, index:int, arr:Array){
			return (element != word_num);
		});
		e.object.alpha = 0.5;
	}
	
	var t:Transitioner = new Transitioner(0.5);
	vis.data.nodes.visit(function(d:DataSprite):void {
		t.$(d).visible = _shown.indexOf(d.data.series) != -1;
	});
	vis.data.edges.visit(function(d:DataSprite):void {
		t.$(d).visible = _shown.indexOf(d.data.series) != -1;
	});
	
	var max:Number = 0;
	for each(var d:DataSprite in vis.data.nodes){
		if(d.data.count > max && _shown.indexOf(d.data.series) != -1)
			max = d.data.count;
	}
	vis.operators[0].yScale.preferredMax = max;
	
	update(t);
}).attach(_legend);

private function update(t:Transitioner):void{
	// toggle screen quality during animation to boost frame rate
	t.addEventListener(TransitionEvent.START, function(e:Event):void{
	});
	t.addEventListener(TransitionEvent.END, function(e:Event):void{
	});	
	vis.update(t).play();
}

So _shown is now an array instead, it will contain the series numbers of the graphs we want to display. With the help of this array we also determine which legends to highlight. They all start out as fully visible but when a legend is clicked only the corresponding graph is shown and all other legend buttons are grayed out.

We begin by determining which word was clicked and it’s series number, which is also its position in the words array. If it’s not already in the _shown array we push it on top and set its legend to fully visible. Otherwise we remove it by running a filter callback and assigning the result to _shown and setting the corresponding legend label to half visible.

Next we create a transitioner and loop through all nodes (circles) and edges (the lines between them), if their series number is in _shown they are shown, if not they will not be shown. Note the use of the transitioner’s $() function here to collect all changes we want to work with.

Finally it’s time to rescale the y-axis so that it always barely contains the currently displayed plots, note the use of the y scalefactor’s preferredMax property to achieve this.

The custom update() function isn’t really doing anything at the moment except making the transitions somewhat faster (maybe). Vis.update(t) will return the transitioner, that’s why we can chain play() to it.

Let’s move on to #2:

var distort = new FisheyeDistortion(3,3,0);
//var distort = new BifocalDistortion(0.1, 3, 0.1, 3);
distort.distortSize = false;
distort.enabled = false;
vis.operators.add(distort);
vis.controls.add(new AnchorControl(distort as Layout));

var show:Link = new Link("Toggle Magnifier");
show.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void{
	vis.operators[5].enabled = (vis.operators[5].enabled == false);
	update(new Transitioner(1));
});
show.x = 20;
show.y = 420;
addChild(show);

The Link class is something I just ripped 100% from the flare.demo.utils package. Note how we keep track of where the distort operator is in the operator list, in this case at #5.

Not really much to add here, we toggle the enabled attribute on or off.

And finally #3:

. . .
//in the visualize function:
vis.controls.add(new TooltipControl(Sprite, null, updateTooltip, updateTooltip, null, 50));
. . .
private function updateTooltip(e:TooltipEvent):void{
	var date = new Date(int(vis.xyAxes.xAxis.value(vis.mouseX, vis.mouseY)));
	var count = Math.round(vis.xyAxes.yAxis.value(vis.mouseX, vis.mouseY));
	var strDate = String(date.date) + " " + months[date.month];
	TextSprite(e.tooltip).htmlText = Strings.format("Count: {0}<br/>Date: {1}", count, strDate);
}

We setup a TooltipControl and set its over and out callbacks to the same function: updateTooltip. We begin by collecting the date which will be a unix timestamp, from the x-axis and proceed to convert it to a Date object. The Date object will be used to create strDate which could look like “12 Sep” for instance. The thought here is that the year will not be needed as it is easily visible on the x-axis itself.

Finally we format the tooltip textsprite with our info.

Related Posts

Tags: , , , , , , , ,