Column charts with ticks

After having some issues with the Flex Forum due to spamming (not me), I went back on to answer a few quick questions. A question about creating tick lines between the interval lines on a column chart was followed up with setting the number of tick lines between the intervals. The first part of adding tick lines is fairly straight forward. When you create a ColumnChart and add LinearAxis, you can set the minorInterval value, which creates the ticks between the main intervals. After that is set, you can add an AxisRenderer to the verticalAxisRender to adjust what the tick looks like.

<mx:verticalAxisRenderers>
	<mx:AxisRenderer axis="{countAxis}" minorTickPlacement="inside" minorTickStroke="{s1}" minorTickLength="330" />
</mx:verticalAxisRenderers>

As part of the question, the user wanted to create grid lines, which to me was to stretch the tick line across the entire chart. In order to have the tick lines only show up on the chart, you need to set the placement to “inside” and set the length. Unfortunately, you can’t simply get the width of the chart and set the length of the tick line, because the chart also includes any legends and interval numbers. Also, the tick line is white, so if you want it to match the grid lines, you need to create a stroke and set that value.

Finally, the user asked if the number of tick lines could be manipulated. What I found was that the chart would take the main interval value and divided it by the minor interval value in order to show the number of ticks, including the tick at the interval value. So, I came up with the simple formula to determine the minorInterval value based on a users selection. I added the value to a change function for a droplist of 1-9. The value 0 doesn’t work, because once you set it to show the minorInterval, it will always show something.

Minor Interval Value = Major Interval Value / (Viewable Tick Count + 1)

protected function tickViewList_changeHandler(event:IndexChangeEvent):void
{
	var tickCount:int = tickViewList.selectedItem;
	var tickView:Number = countAxis.interval / (tickCount + 1);
	countAxis.minorInterval = tickView;
}

View Source

Column Chart with Item Renderer

When doing the Column Chart with fillFunction for a question in the Flex Forum, the poster said that he was trying to do something a little different. Instead of a simple fill, he wanted the fill to be semi-transparent with a solid border. When I looked at the iFill function, it didn’t have a stroke option and it doesn’t seem that the standard column item deals with the column border. My guess was, that an item renderer should be used for the column instead. Within the item render, you can create a rectangle graphic and then adjust the border and fill parameters. Since this seemed like an interesting exercise, I decided to make myself an example (the best way I learn something).

I started out using the simple array data found in other examples. I will probably update this to something more dynamic later.

[Bindable]
public var SMITH:ArrayCollection = new ArrayCollection([{date:10, close:41.87, open: 30},{date:20, close:45.74, open: 40}, 
{date:30, close:42.77, open: 60}, {date:40, close:48.06, open: 50}]);

And then I attached this to a ColumnChart and create a single ColumnSeries with the “date” on the xAxis and the “close” count on the yAxis. I then added the itemRenderer parameter, which popups a window for creating the component.

<mx:ColumnChart id="myColumnChart1" dataProvider="{SMITH}" >
	<mx:horizontalAxis>
		<mx:CategoryAxis categoryField="date" />
	</mx:horizontalAxis>
	<mx:series>
		<mx:ColumnSeries id="columnSeries1" xField="date" yField="close" itemRenderer="components.myColumnRenderer" />
	</mx:series>
</mx:ColumnChart>

In the ItemRender, the way to kick everything off is to override the set data function. You have to check to see if the value is null first, or you get errors when the chart is initially loading. Once there is data in the value, then you can start altering the renderer for the column.

override public function set data(value:Object):void {
	super.data = value;

	// Check to see if the data property is null.
	if (value== null) {
		return;
	} else {
		// data display and other stuff start here
	}
}

To create the background rectangle, you first have to start with a Graphic and then add the Rect and the parts of the Rect that you want to alter. You could just add the Rect and then alter the stroke and fill dynamically, but having them already defined makes it a little easier. I am only doing a Solid stroke and fill, if you wanted to do gradient or mix gradient and solid, then you definitely would want to do that dynamically. The Graphic is first, since it is on the bottom. Anything you want to display above the rectangle graphic goes afterward in the code.

<s:Graphic>
	<s:Rect id="columnRect">
		<s:stroke>
			<s:SolidColorStroke id="rectSolidColorStroke" />
		</s:stroke>
		<s:fill>
			<s:SolidColor id="rectSolidColor" />
		</s:fill>
	</s:Rect>
</s:Graphic>

Once you are ready to alter the column, you have to create the rectangle graphic for the background and you need to set the width and height to the super call for the column. If you don’t do this, then the rectangle is size 0 and you can’t see anything.

columnRect.width = super.width;
columnRect.height = super.height;

Since you are passing in the column data, you can modify the look of each column either by the xValue or the yValue. In this case, I wanted to change each column based on the yValue. I am only doing a simple solid fill and solid stroke, so I only need to change one color. I declared the colors to make it easier to set the uint values. Finally, I adjust the stroke weight and the fill alpha. These could also be changed based on the column data.

switch(value.xValue) {
	case 10:
		// Red Color
		columnFillColor = colorRed;
		columnStrokeColor = colorRed;
		break;
	case 20:
		// Blue Color
		columnFillColor = colorBlue;
		columnStrokeColor = colorBlue;
		break;
	case 30:
		// Green Color
		columnFillColor = colorGreen;
		columnStrokeColor = colorGreen;
		break;
	case 40:
		// Purple Color
		columnFillColor = colorPruple;
		columnStrokeColor = colorPruple;
		break;
}

rectSolidColorStroke.color = columnFillColor;
rectSolidColorStroke.weight = 2;
rectSolidColor.color = columnStrokeColor;
rectSolidColor.alpha = .3;

This example didn’t take very long to make and I will probably try to add some other feature to this simple chart.
View Source

Column Chart with Fill Function

When you have a column chart, sometimes you want to change the column colors based on the data. A question in the Flex Forum asked how to alter the column color on each column. To do this, yo need to use the fillFunction on a ColumnSeries to set the color of the fill. One issue with doing this, is how it affects the chart legend.

If you use the fills property or the fillFunction to define the fills of chart items, and you want a legend, you must manually create the Legend object for that chart.

But, this just gives me the opportunity to test out two different charting options.

I alter the stacked column chart that I created to answer another question on the forum. Since the column chart in this example is created dynamically, I had to add the fillFunction parameter when creating the column series for the green and red apple columns.

columnSeries1.fillFunction = greenAppleFillFunction;

Then I just created a simple function to change the color of the column if the count was less than 50.

private function greenAppleFillFunction(element:ChartItem, index:Number):IFill {
	var item:ColumnSeriesItem = ColumnSeriesItem(element);
	var count:Number = Number(item.yValue);

	if (count < 50) {
		return scFadeGreen;
	} else {
		return scGreen;,
	}
}

To make things easier, I had already defined my SolidColor values, this makes it easier to keep it consistent throughout the chart. In this example, I am only getting the yValue, but you could also get the xValue, if you wanted to change the column colors based on that.

Next I need to update the legend to reflect the new fillFunctions, which is fairly straight forward and I can also use the defined SolidColor parameters.

<mx:Legend  direction="horizontal" >
	<mx:LegendItem label="Red Apples" fill="{scRed}" />
	<mx:LegendItem label="Red under 50" fill="{scFadeRed}" />
	<mx:LegendItem label="Yellow Apples" fill="{scYellow}" />
	<mx:LegendItem label="Green Apples" fill="{scGreen}" />
	<mx:LegendItem label="Green under 50" fill="{scFadeGreen}" />
</mx:Legend>

I also added a Refresh Data button so that the data can be cycled and the column color changes can be seen.
View Source

Stacked Column Chart with Line Series

On the Flex Forum, I was attempting to help someone find their issue to a Stacked Column Chart with a Line Series. The y-axes values were not corresponding with the data being provided. This seemed like a glitch and I even attempted a work around by finding the minimum and maximum values. Finally, after looking at the Stacking Columns example and the Multiple Axis Example, reconstructed the chart using the static objects instead of dynamically creating the chart. From there, I recreated the chart items in a function and determined that the first issue the poster was having was building the column series incorrectly into a column set.

// add column series to column set
columnset.series = [columnSeries1, columnSeries2];

The second issues is that the created column set and the line series would be the two series added to the chart, not the individual column series.

myChart.verticalAxisRenderers = [verticalAxisRendererRight, verticalAxisRendererLeft];
// column set and linear series to Chart
myChart.series = [columnset, lineSeries];

I also added both x-axis and y-axis data column information, so that there would be no mistake as to were the data was coming from. These small changes apparently were the key to getting the axis values to match the column and charts.

var columnSeries1:ColumnSeries = new ColumnSeries();
columnSeries1.dataProvider = acChartData;
columnSeries1.xField = "hourOfDay";
columnSeries1.yField = "greenAppleCount";
columnSeries1.displayName = "Green";
columnSeries1.setStyle("fill", 0x009900);
columnSeries1.verticalAxis = verticalAxisLeft;

I used my apples data creator for this chart, since I already had that available on the other chart.
Another side note of obviousness, you fill columns and stroke lines.

View Source