Here is a question that came up earlier this morning on a mailing list. How can we specify colors for CFCHART based on some particular business rule? So for example, imagine we have a set of average temperatures. You want to chart them and specifically call out values that are below, or above, certain notes. This is rather simple if you make use of the colorList attribute of cfchartseries. Normally this is used to provide a static list of colors, but you can certainly make it dynamic as well. Here is a simple example.
Let's start off with some simple, static data, and no, this isn't real temperatures for Louisiana.
Ok, so it works. I'm not exactly sure where the Halloween Orange theme came from, but it works. So now let's make it dynamic. I'm going to use the following rules for my colors:
Not exactly a work of art, but better. You can quickly see which items are at the extreme of my data set. I've pasted the complete template below.
1 <cfset data = arrayNew(2)>
2 <cfset data[1][1] = "Jan">
3 <cfset data[1][2] = 30>
4 <cfset data[2][1] = "Feb">
5 <cfset data[2][2] = 60>
6 <cfset data[3][1] = "Mar">
7 <cfset data[3][2] = 70>
8 <cfset data[4][1] = "Ap">
9 <cfset data[4][2] = 80>
10 <cfset data[5][1] = "May">
11 <cfset data[5][2] = 85>
12 <cfset data[6][1] = "Jun">
13 <cfset data[6][2] = 95>
14 <cfset data[7][1] = "Jul">
15 <cfset data[7][2] = 105>
16 <cfset data[8][1] = "Aug">
17 <cfset data[8][2] = 104>
18 <cfset data[9][1] = "Sep">
19 <cfset data[9][2] = 95>
20 <cfset data[10][1] = "Oct">
21 <cfset data[10][2] = 80>
22 <cfset data[11][1] = "Nov">
23 <cfset data[11][2] = 75>
24 <cfset data[12][1] = "Dec">
25 <cfset data[12][2] = 60>
Next, let's supply this to a cfchart just to see how it looks without any modification:
2 <cfset data[1][1] = "Jan">
3 <cfset data[1][2] = 30>
4 <cfset data[2][1] = "Feb">
5 <cfset data[2][2] = 60>
6 <cfset data[3][1] = "Mar">
7 <cfset data[3][2] = 70>
8 <cfset data[4][1] = "Ap">
9 <cfset data[4][2] = 80>
10 <cfset data[5][1] = "May">
11 <cfset data[5][2] = 85>
12 <cfset data[6][1] = "Jun">
13 <cfset data[6][2] = 95>
14 <cfset data[7][1] = "Jul">
15 <cfset data[7][2] = 105>
16 <cfset data[8][1] = "Aug">
17 <cfset data[8][2] = 104>
18 <cfset data[9][1] = "Sep">
19 <cfset data[9][2] = 95>
20 <cfset data[10][1] = "Oct">
21 <cfset data[10][2] = 80>
22 <cfset data[11][1] = "Nov">
23 <cfset data[11][2] = 75>
24 <cfset data[12][1] = "Dec">
25 <cfset data[12][2] = 60>
1 <cfchart chartheight="500" chartwidth="600" title="Average Temperature" show3d="false" >
2 <cfchartseries type="bar" paintstyle="shade">
3 <cfloop index="datum" array="#data#">
4 <cfchartdata item="#datum[1]#" value="#datum[2]#">
5 </cfloop>
6 </cfchartseries>
7 </cfchart>
This results in the rather lovely chart you see here:
2 <cfchartseries type="bar" paintstyle="shade">
3 <cfloop index="datum" array="#data#">
4 <cfchartdata item="#datum[1]#" value="#datum[2]#">
5 </cfloop>
6 </cfchartseries>
7 </cfchart>
Ok, so it works. I'm not exactly sure where the Halloween Orange theme came from, but it works. So now let's make it dynamic. I'm going to use the following rules for my colors:
- If the temperature was less than 40, use blue (get it?).
- If the temperature was greater than 90, use red (clever, I know).
- Otherwise just use green.
1 <cfset cList = "">
2 <cfloop index="datum" array="#data#">
3 <cfif datum[2] lt 40>
4 <cfset cList = listAppend(cList, "##0000FF")>
5 <cfelseif datum[2] gt 90>
6 <cfset cList = listAppend(cList, "##FF0000")>
7 <cfelse>
8 <cfset cList = listAppend(cList, "##00FF00")>
9 </cfif>
10 </cfloop>
Next I passed in cList:
2 <cfloop index="datum" array="#data#">
3 <cfif datum[2] lt 40>
4 <cfset cList = listAppend(cList, "##0000FF")>
5 <cfelseif datum[2] gt 90>
6 <cfset cList = listAppend(cList, "##FF0000")>
7 <cfelse>
8 <cfset cList = listAppend(cList, "##00FF00")>
9 </cfif>
10 </cfloop>
1 <cfchartseries type="bar" colorlist="#cList#" paintstyle="shade">
And voila:
Not exactly a work of art, but better. You can quickly see which items are at the extreme of my data set. I've pasted the complete template below.
1 <cfset data = arrayNew(2)>
2 <cfset data[1][1] = "Jan">
3 <cfset data[1][2] = 30>
4 <cfset data[2][1] = "Feb">
5 <cfset data[2][2] = 60>
6 <cfset data[3][1] = "Mar">
7 <cfset data[3][2] = 70>
8 <cfset data[4][1] = "Ap">
9 <cfset data[4][2] = 80>
10 <cfset data[5][1] = "May">
11 <cfset data[5][2] = 85>
12 <cfset data[6][1] = "Jun">
13 <cfset data[6][2] = 95>
14 <cfset data[7][1] = "Jul">
15 <cfset data[7][2] = 105>
16 <cfset data[8][1] = "Aug">
17 <cfset data[8][2] = 104>
18 <cfset data[9][1] = "Sep">
19 <cfset data[9][2] = 95>
20 <cfset data[10][1] = "Oct">
21 <cfset data[10][2] = 80>
22 <cfset data[11][1] = "Nov">
23 <cfset data[11][2] = 75>
24 <cfset data[12][1] = "Dec">
25 <cfset data[12][2] = 60>
26
27 <cfset cList = "">
28 <cfloop index="datum" array="#data#">
29 <cfif datum[2] lt 40>
30 <cfset cList = listAppend(cList, "##0000FF")>
31 <cfelseif datum[2] gt 90>
32 <cfset cList = listAppend(cList, "##FF0000")>
33 <cfelse>
34 <cfset cList = listAppend(cList, "##00FF00")>
35 </cfif>
36 </cfloop>
37
38 <cfchart chartheight="500" chartwidth="600" title="Average Temperature" show3d="false" >
39 <cfchartseries type="bar" colorlist="#cList#" paintstyle="shade">
40 <cfloop index="datum" array="#data#">
41 <cfchartdata item="#datum[1]#" value="#datum[2]#">
42 </cfloop>
43 </cfchartseries>
44 </cfchart>
2 <cfset data[1][1] = "Jan">
3 <cfset data[1][2] = 30>
4 <cfset data[2][1] = "Feb">
5 <cfset data[2][2] = 60>
6 <cfset data[3][1] = "Mar">
7 <cfset data[3][2] = 70>
8 <cfset data[4][1] = "Ap">
9 <cfset data[4][2] = 80>
10 <cfset data[5][1] = "May">
11 <cfset data[5][2] = 85>
12 <cfset data[6][1] = "Jun">
13 <cfset data[6][2] = 95>
14 <cfset data[7][1] = "Jul">
15 <cfset data[7][2] = 105>
16 <cfset data[8][1] = "Aug">
17 <cfset data[8][2] = 104>
18 <cfset data[9][1] = "Sep">
19 <cfset data[9][2] = 95>
20 <cfset data[10][1] = "Oct">
21 <cfset data[10][2] = 80>
22 <cfset data[11][1] = "Nov">
23 <cfset data[11][2] = 75>
24 <cfset data[12][1] = "Dec">
25 <cfset data[12][2] = 60>
26
27 <cfset cList = "">
28 <cfloop index="datum" array="#data#">
29 <cfif datum[2] lt 40>
30 <cfset cList = listAppend(cList, "##0000FF")>
31 <cfelseif datum[2] gt 90>
32 <cfset cList = listAppend(cList, "##FF0000")>
33 <cfelse>
34 <cfset cList = listAppend(cList, "##00FF00")>
35 </cfif>
36 </cfloop>
37
38 <cfchart chartheight="500" chartwidth="600" title="Average Temperature" show3d="false" >
39 <cfchartseries type="bar" colorlist="#cList#" paintstyle="shade">
40 <cfloop index="datum" array="#data#">
41 <cfchartdata item="#datum[1]#" value="#datum[2]#">
42 </cfloop>
43 </cfchartseries>
44 </cfchart>


Comment 1 written by Jody Fitzpatrick on 13 March 2010, at 6:49 AM
But great post... I have always wondered how to do this. I was also wondering if coldfusion could have to sets of data points on the same chart data point a on the left defined by a bar ( or whatever ) and datapoint b defined on the right side with a line chart. I'm sure you have seen something similar to what I'm referring to Ray, well at least I hope so.
Comment 2 written by Raymond Camden on 13 March 2010, at 3:50 PM
Comment 3 written by Larry C. Lyons on 18 March 2010, at 12:21 PM
larry
Comment 4 written by Thrifte on 28 July 2010, at 10:17 AM
Comment 5 written by Raymond Camden on 28 July 2010, at 1:08 PM