Managing labels in charts
Recently, in my daily work, I have come to an issue regarding label management in charts. In many cases, labels are too large to be shown correctly. In order to solve it I have found a workaround, it consists in rotating an abbreviation of the label to take advantage of the available space and showing a tooltip with the whole text.
Label rotation
If we want to rotate the label of the axis we shall use this property: label rotation. This is the way of making it:
<mx:horizontalAxisRenderers>
<mx:AxisRenderer labelRotation="degrees" axis="{id}"/>
</mx:horizontalAxisRenderers>
Where:
- In labelRotation you specify the angle in degrees
- In axis you specify the axis id
And this is the way it should look like:
In order to make this work, the text fonts must be embedded. In this example I am using the MyriadWebPro font that must be located in the assets folder of the project.
<mx:Style>
@font-face{
src: url("../assets/MyriadWebPro.ttf");
fontFamily: myMyriad;
}
ColumnChart {
fontFamily: myMyriad;
fontSize: 20;
}
</mx:Style>
If the chart is inside a flex module the font must be embedded in the Main.mxml, the main application of the project.
Label tooltip
Now, we are going to show a tooltip with different text from that one displayed in the axis label.
Here there is an example of the result working with the months of the year:
And this is the code of the horizontal axis: a custom label renderer must be included to display the tooltip in the desire way. In this case, an object (month) has been created to contain the label and the tooltip instead of a text:
month: {tooltip:tooltip_value,label:label_value}
The function set data is override to extract the data from the month object and initialize the tooltip and the text properties of the label:
<mx:horizontalAxisRenderers>
<mx:AxisRenderer labelRotation="degree" axis="{id}">
<mx:labelRenderer>
<mx:Component>
<mx:Label toolTip="{this.myTip}">
<mx:Script><![CDATA[
[Bindable]
private var myTip:String;
override public function set data(month:Object):void
{
if(month == null)
return;
myTip = month.value.tooltip;
text = month.value.label;
}
]]></mx:Script>
</mx:Label>
</mx:Component>
</mx:labelRenderer>
</mx:AxisRenderer>
</mx:horizontalAxisRenderers>
Tab Navigator
In flex certain events related to tab navigator seem not to be implemented. A solution to this problem is to make use of the button object inside the tab and add listeners to the events you want linked to the button.
First of all, in the creation complete of tab navigator a function (enableClick()) assigns each button of th tab an id and an event listener, as shown:
<mx:TabNavigator id="tabnavigator_id" creationComplete="enableClick()">
<mx:VBox label="first_tab_label">
</mx:VBox>
<mx:VBox label="second_tab_label">
</mx:VBox>
</mx:TabNavigator>
public function enableClick():void{
for (var i:int=0; i< tabnavigator_id.getChildren().length; i++) {
var tab:Button = tabnavigator_id.getTabAt(i);
tab.id = tab.label;
tab.addEventListener(FlexEvent.BUTTON_DOWN,myTabClickHandler);
}
}
Now, the id assigned to the button is used in the event listener to identify the tab and therefore perform the business logic:
public function myTabClickHandler(event:FlexEvent):void{
if(event.target.id == “condition”){
business_logic
}
}
Date Chooser
With the Date Chooser we have build an informative calendar so the user cannot interact with it.
One way to achieve this is avoiding user events with event.preventDefault, however there is another one easier using CSS.
That is, in the calendar style the rollOverColor and selectionColor properties should be the same as the background theme color.
DateChooser
{
corner-radius: 4;
border-thickness: 1;
horizontalGap: 0;
verticalGap: 3;
headerColors: #f2ede9, #dad5d2;
fillColors: #FFFFFF, #CCCCCC, #FFFFFF, #EEEEEE;
todayColor: #443322;
rollOverColor: #EDEBE9;
selectionColor: #EDEBE9;
color: #443322;
borderColor: #A59B93;
iconColor: #443322;
backgroundColor: #FFFFFF;
backgroundAlpha: 0.8;
themeColor: #CC6600;
}
Besides, certain dates in the calendar can be highlighted. In the example shown below, all weekends are highlighted:
The way to make this work is extending DateChooser and overriding updateDisplayList function:
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
//Last row with saturday in order to know the last weekend to highligh
var rowIndexFinal:int = (this.mx_internal::dateGrid.dayBlocksArray[5][6].text == "")? ((this.mx_internal::dateGrid.dayBlocksArray[5][5].text == "")?4:5) : 6;
//Highlight each weekend
for(var j:int = 1; j<=rowIndexFinal; j++){
//Saturday (if the month starts in Sunday avoid highlighting a cell without date)
if(this.mx_internal::dateGrid.dayBlocksArray[5][j].text != ""){
this.mx_internal::dateGrid.dayBlocksArray[5][j].background = true;
this.mx_internal::dateGrid.dayBlocksArray[5][j].backgroundColor = 0xbc9970;
this.mx_internal::dateGrid.dayBlocksArray[5][j].alpha = 0.8
this.mx_internal::dateGrid.dayBlocksArray[5][j].setColor(0xFFFFFF);
}
//Sunday (if the month ends in Saturday avoid highlighting a cell without date)
if(this.mx_internal::dateGrid.dayBlocksArray[6][j].text != ""){
this.mx_internal::dateGrid.dayBlocksArray[6][j].background = true;
this.mx_internal::dateGrid.dayBlocksArray[6][j].backgroundColor = 0xbc9970;
this.mx_internal::dateGrid.dayBlocksArray[6][j].alpha = 0.8
this.mx_internal::dateGrid.dayBlocksArray[6][j].setColor(0xFFFFFF);
}
}
}
Useful links