This isn't happening. Instead, the maximum value of the axis is set to the value of the largest column. That column then takes up 100% of the available space. Since there is no room for a label outside the column, Flex moves it inside.
The code in ColumnChart that does this is:
if(v.labelIsHorizontal)
{
if(v.y < (isNaN(v.min) ? base : v.min))
{
v.labelY = v.y - v.labelHeight;
if(v.labelY < this.dataRegion.top)
v.labelY = v.y;
}
else
{
v.labelY = v.y;
if(v.labelY > this.dataRegion.bottom)
v.labelY = v.y - v.labelHeight;
}
v.labelX = v.x - columnSeries.seriesRenderData.renderedHalfWidth +columnSeries.seriesRenderData.renderedXOffset;
}
I had an unbending requirement that all labels must render outside the column, so if I had a bar or column chart with labelPosition = "outside", I'd have to pad the axis/axes maximum values to provide enough space for the outside label.
My component was a base cartesian chart that could dynamically render series. When generating the series or after a user re-sized the chart, I would check if I needed padding, and would call:
if(padAxes){
callLater(padAxesMaximums);
}
That padAxesMaximums function looks something like this:
private function padAxesMaximums():void {
if(!_padAxesRequestPending){
return;
}
_padAxesRequestPending = false;
var axisLength:Number;
var axisMax:Number;
var clearance:Number;
var i:int;
var j:int;
var k:int;
var items:Array;
var label:Label;
var labelContainer:Sprite;
var pad:Number;
var tmpNum:Number;
// Map
// key = IAxis object - references a particular axis ( primary or secondary )
// value = maximum axis value ( NOT pixels )
var maxAxisSuggestion:Dictionary = new Dictionary();
if(theChart.series == null){
return;
}
if(theChart is BarChart){
for(i = 0; i < theChart.series.length; i++){
axisLength = 0;
for(k = 0; k < theChart.horizontalAxisRenderers.length; k++){
if(theChart.horizontalAxisRenderers[k].axis == theChart.series[i].horizontalAxis){
axisLength = theChart.horizontalAxisRenderers[k].length;
break;
}
}
if(axisLength == 0){
return;
}
labelContainer = theChart.series[i].labelContainer;
pad = theChart.getStyle("paddingRight");
clearance = theChart.computedGutters.right + pad;
items = theChart.series[i].items;
if(items == null || labelContainer == null || items.length != labelContainer.numChildren){
continue;
}
axisMax = 0;
for(j = 0; j < items.length; j++){
var bsi:BarSeriesItem = items[j];
label = labelContainer.getChildAt(j) as Label;
if((bsi.x + label.textWidth + clearance) > axisLength){
//we have a label stuck inside, yearning to be outside
tmpNum = Math.ceil(theChart.series[i].horizontalAxis.computedMaximum * axisLength / (axisLength - clearance - label.textWidth));
// take the maximum of the current running value, or the newly calcualted value.
axisMax = Math.max(tmpNum, axisMax);
}
// after looping through all of the labels and seeing
// what the max would be - then set the max
if( isNaN( maxAxisSuggestion[theChart.series[i].horizontalAxis] ) ) {
maxAxisSuggestion[theChart.series[i].horizontalAxis] = 0;
}
maxAxisSuggestion[theChart.series[i].horizontalAxis] = Math.max(maxAxisSuggestion[theChart.series[i].horizontalAxis], axisMax);
}//end iteration over BarSeriesItems
}//end iteration over BarSeries
}
else if(theChart is ColumnChart){
for(i = 0; i < theChart.series.length; i++){
labelContainer = theChart.series[i].labelContainer;
pad = theChart.getStyle("paddingTop");
clearance = theChart.computedGutters.top + pad;
items = theChart.series[i].items;
if(items == null || labelContainer == null || items.length != labelContainer.numChildren){
continue;
}
axisMax = 0;
for(j = 0; j < items.length; j++){
var csi:ColumnSeriesItem = items[j];
label = labelContainer.getChildAt(j) as Label;
if(csi.y < (clearance + label.height)){
//we have a label stuck inside, yearning to be outside
tmpNum = Math.ceil(theChart.series[i].verticalAxis.computedMaximum * csi.min / (csi.min - clearance - label.height));
// take the maximum of the current running value, or the newly calcualted value.
axisMax = Math.max(tmpNum, axisMax);
}
}
// after looping through all of the labels and seeing
// what the max would be - then set the max
if( isNaN( maxAxisSuggestion[theChart.series[i].verticalAxis] ) ) {
maxAxisSuggestion[theChart.series[i].verticalAxis] = 0;
}
maxAxisSuggestion[theChart.series[i].verticalAxis] = Math.max(maxAxisSuggestion[theChart.series[i].verticalAxis], axisMax);
}
}
for ( var key:Object in maxAxisSuggestion ) {
var keyAxis:LinearAxis = key as LinearAxis;
if( keyAxis != null ) {
var value:Number = maxAxisSuggestion[key] as Number;
keyAxis.maximum = value;
}
}
}
Padding the column chart was easiest, because the length of the axis was available as the "min" parameter on the ColumnSeriesItem. For the bar chart, I had to iterate through the horizontalAxisRenderers to find the length.

No comments:
Post a Comment