PDA

View Full Version : How to change the color of a POINT based on it's value



jlawton
25 Oct 2012, 6:39 AM
Hello all,

I have a line chart and I'd like to change the color of the point based on it's value (or really any time, but based on value makes for a good example). I have the following code, and you can mess with it at the following link here (http://jsfiddle.net/s4AFU/). I think this could be useful for a lot of people to know how to do and I can't find any examples of it anywhere.


Ext.onReady(function() {
Ext.define('tempModel', {
extend: 'Ext.data.Model',
fields: ['letter', 'number']
});

var tempStore = Ext.create('Ext.data.Store', {
model: 'tempModel',
data: [{ letter:"A", number: 48},
{ letter:"B", number: 72},
{ letter:"C", number: 64},
{ letter:"D", number: 29},
{ letter:"E", number: 37},
{ letter:"F", number: 51},
{ letter:"G", number: 35},
{ letter:"H", number: 90},
{ letter:"I", number: 61},
{ letter:"J", number: 19} ]
});

Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 470,
height: 300,
store: tempStore,
axes: [
{
title: 'Numbers',
type: 'Numeric',
position: 'left',
fields: ['number'],
},
{
title: 'letter',
type: 'Category',
position: 'bottom',
fields: ['letter'],
title: 'letter',
grid: true,
label: {
rotate: {
degrees: 90
}
}
}],
series: [
{
type: 'line',
xField: 'letter',
yField: 'number',
renderer : function (sprite, record, attributes, index, store) {
/*
if (record.number <= 30) {
attributes.fill = '#ff0000';
} else if (record.number >= 70) {
attributes.fill = '#00ff00';
} else {
attributes.fill = '#0000ff';
}
*/
return attributes;
},
tips : {
trackMouse : true,
width : 200,
height: 40,
renderer : function(storeItem, item) {
this.update(storeItem.get('letter') + ' ' + storeItem.get('number'));
}
}
}
]
});
});?

In the series, I have a renderer, but I'm not sure how to get the value of the current record. I've tried record.number and record.get('number') and store.getAt(index) (which get's you the record again)... I'm stuck!

Any suggestions would be greatly appreciated!

Thanks

Farish
25 Oct 2012, 7:08 AM
I looked up the API Documentation for line series: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.chart.series.Line-cfg-renderer

the comments on it say that there is some problem with the record (is not always correct) and recommend that instead of using store.getAt(index), you should use the following:


var correctRecord = chart.series.items[known series index].items[index].storeItem;

where known series index would be 0 in your case if you are using only one series.

jlawton
25 Oct 2012, 8:20 AM
Thanks for the link to that, it almost helped, but it doesn't seem to be working.

In the code example he has:



var chartId = sprite.surface.id;
var chart = Ext.getCmp(chartId);


When I console.log chart, I don't get a value (I get undefined). I think that's because I'm doing this while rendering the chart, and this example is for after the chart has been rendered.

So is there a way for me to do this while creating the chart? Or am I going to end up creating the chart, and then going over it a second time and styling it as needed?

Farish
25 Oct 2012, 8:32 AM
you can do it inside the chart creation. you should be able to access the chart itself somehow inside the renderer function. getCmp will return undefined because you are not defining an id for the chart. Its not recommended (using an id) but for now, try the following: assign an id to your chart and then inside your renderer, use that id to get the chart. see if that works.

var chart = Ext.getCmp('chart_id');

jlawton
25 Oct 2012, 9:23 AM
What I'm saying is that with the jsfiddle (http://jsfiddle.net/eUmJX/4/)I set up, you can see that while the first line of the code that gets the chartId works correctly, the second line that gets the chart object does not.



var chartId = sprite.surface.id; // this works and returns a valid chartId
var chart = Ext.getCmp(chartId); // this returns undefined

Farish
25 Oct 2012, 9:31 AM
getCmp works with a unique id which is not what chartId holds. see the documentation for Ext.getCmp(). the id should be configured on the chart.


Ext.create('Ext.chart.Chart', {
id: 'chart_id', // this is the id which you can use in Ext.getCmp('chart_id');
renderTo: Ext.getBody(),
...

});

jlawton
25 Oct 2012, 9:41 AM
You've been a great help so far, and I think we're almost there.

I gave the chart a unique id, and now it almost works, except I get an error when trying to access the "storeItem".

You can check out the jsfiddle here (http://jsfiddle.net/eUmJX/9/). If you append ".storeItem" to the console.log line in the renderer you'll see the error "Uncaught TypeError: Cannot read property 'storeItem' of undefined" happens.

Farish
25 Oct 2012, 9:54 AM
i cant see the console.log output in the fiddle you linked. dont know what is wrong. I can only try tomorrow when i get back to work.

Anyway, one thing which you dont need is the id. "this" should be the series in the renderer function. Do console.log(this) and see if it is infact the series, if so, you dont need to first get the chart, you can use this.items[index]

jlawton
25 Oct 2012, 9:58 AM
If you're in chrome you can just hit control+shift+j to bring it up. In jsfiddle you won't be able to call Ext.stuff from the console though. You are correct though, I put in a 'console.log(this)' and it did return the series info, so maybe I can get the store info from that. Not sure. I'll update this thread if I find any more info.

Farish
25 Oct 2012, 10:09 AM
the first time, chart.series.items[0].items[index] is undefined. thats what is causing the problem. You can get it working using the following:


if(chart.series.items[0].items[index])
console.log(chart.series.items[0].items[index].storeItem.data.number);

Now the value of the number field will be printed!

jlawton
25 Oct 2012, 10:50 AM
Ah yes! That got it to work!! While playing with it a bit more, I noticed that as long as I gave it an id, I could use the original code you linked to, where it was calling



var chartId = sprite.surface.id;
var chart = Ext.getCmp(chartId); // this works as long as I have some id defined in the chart object, even if I'm not calling it here as I was earlier.


You can play with the final results on jsfiddle here (http://jsfiddle.net/eUmJX/21/).

Thanks again!

Farish
25 Oct 2012, 1:13 PM
you can now remove the id and instead, use the "this" for accessing the series directly:

Replace
chart.series.items[0].items[index]
by
this.items[index]

you can reduce the code a little by removing the lines related to chart's id. Also, using an id is considered bad practice. you can use component query instead.

jlawton
15 Nov 2012, 7:20 AM
Is there a way to change the chart point from a point to an image? I just want to change one of the points though. (in this instance, the last one). Not sure where to look for that info. TIA.