Mark custom chart bar color to legend in EXT JS 5 - extjs

I have an issue while using custom legend color in EXTJS 5 chart. I can apply custom color to the chart legend but i cannot apply that to the legend item. In EXT JS 4, i can use one override function to in series to handle it. like
getLegendColor: function(index) {
var proSpeciality = ["#EFD07B","#0082AD"];
return proSpeciality[index];
}
But this is not available in EXT JS 5.
Sample code.
Ext.create('Ext.Container', {
renderTo: Ext.getBody(),
width: 600,
height: 400,
layout: 'fit',
items: {
xtype: 'cartesian',
store: {
fields: ['name', 'value','value2'],
data: [
{name: 'metric one', value: 10,value2: 15},
{name: 'metric two', value: 7,value2: 15},
{name: 'metric three', value: 5,value2: 15},
{name: 'metric four', value: 2,value2: 15},
{name: 'metric five', value: 27,value2: 15}
]
},
axes: [{
type: 'numeric',
position: 'left',
title: {
text: 'Sample Values',
fontSize: 15
},
fields: 'value'
}, {
type: 'category',
position: 'bottom',
title: {
text: 'Sample Values',
fontSize: 15
},
fields: 'name'
}],
legend: {
docked: 'top',
style: {
stroke: '#ffffff',
'stroke-width': 2,
opacity: 1
},
tpl: [
'<tpl for="."> ',
' <div class="myLegendItem" style="float:left;margin:5px;padding:0px;cursor:pointer;">',
' <div class="" style="float:left;margin:2px;width:12px;height: 12px; background:{mark};"></div><div style="float:left;">{name}</div> ',
' </div> ',
' </tpl>'
],
itemSelector: '.myLegendItem'
},
series: {
type: 'bar',
xField: ['name'],
yField: ['value','value1'],
stacked: false,
renderer: function(sprite, record, attributes, index, store) {
var proSpeciality = ["#EFD07B","#0082AD","#00A67B","#AD1808","#520084"];
attributes.fill = proSpeciality[index % proSpeciality.length];
return attributes;
},
getLegendColor: function(index) {
var proSpeciality = ["#EFD07B","#0082AD"];
return proSpeciality[index];
}
}
}
});
Please let me know if i need to change something.
Thanks in advance

Try to use "colors" property within series:
series: {
type: 'bar',
colors: ['orange', 'yellow'],
...
}
Example: https://fiddle.sencha.com/#fiddle/bk1

Answering the question about 'global colour arrays' (which I can't answer in the comments section - not enough reputation. Aleksei Mialkin is quite right in his solution), you can use a singleton to hold these sorts of values
Ext.define("MyApp.colours", {
singleton: true,
COL1: 'orange',
COL2: 'red',
COL3: 'blue',
COL4: 'green'
});
Then reference as
...
colors: [MyApp.colours.COL1, MyApp.colours.COL2],
...

Related

ExtJS : line chart : How to get image base64 when the chart finish draw ?

I use ExtJS to create a line chart and create a button to get image base64.Now, I don't want this button. I need an event whitch fire when the line chart finish draw and then get image base64. I found an event "painted", and I try to use it, but it can't work, Why?.
reference:ExtJS line chart example
Works just fine for me.
Cartesian Graph with a series and some lines inside that.
Add painted listener to the cartesian graph, call getImage('stream') on the cartesian graph (this), check out the data element of the returned object.
I merely added this listener configuration to the cartesian which will display the png data for the full graph in a MessageBox:
listeners: {
painted: function(element, eOpts) {
Ext.Msg.alert('Image Data', this.getImage('stream').data);
}
},
See below for the adjusted full example from the documentation:
Ext.create({
xtype: 'cartesian',
renderTo: document.body,
width: 600,
height: 400,
insetPadding: 40,
listeners: {
painted: function(element, eOpts) {
Ext.Msg.alert('Image Data', this.getImage('stream').data);
}
},
store: {
fields: ['name', 'data1', 'data2'],
data: [{
'name': 'metric one',
'data1': 10,
'data2': 14
}, {
'name': 'metric two',
'data1': 7,
'data2': 16
}, {
'name': 'metric three',
'data1': 5,
'data2': 14
}, {
'name': 'metric four',
'data1': 2,
'data2': 6
}, {
'name': 'metric five',
'data1': 27,
'data2': 36
}]
},
axes: [{
type: 'numeric',
position: 'left',
fields: ['data1'],
title: {
text: 'Sample Values',
fontSize: 15
},
grid: true,
minimum: 0
}, {
type: 'category',
position: 'bottom',
fields: ['name'],
title: {
text: 'Sample Values',
fontSize: 15
}
}],
series: [{
type: 'line',
style: {
stroke: '#30BDA7',
lineWidth: 2
},
xField: 'name',
yField: 'data1',
marker: {
type: 'path',
path: ['M', - 4, 0, 0, 4, 4, 0, 0, - 4, 'Z'],
stroke: '#30BDA7',
lineWidth: 2,
fill: 'white'
}
}, {
type: 'line',
fill: true,
style: {
fill: '#96D4C6',
fillOpacity: .6,
stroke: '#0A3F50',
strokeOpacity: .6,
},
xField: 'name',
yField: 'data2',
marker: {
type: 'circle',
radius: 4,
lineWidth: 2,
fill: 'white'
}
}]
});

How to use HTML tags in a Chart Legend?

How can use HTML tags in a chart legend while using title to apply custom legend text?
If we apply something like this title:['Your<b>New</b><br />Label'] the tags are just written as plain text.
Ext.application({
name: 'Fiddle',
launch: function () {
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data', 'data2'],
data: [{
'name': 'metric one',
'data': 10,
'data2': 2
}, {
'name': 'metric two',
'data': 27,
'data2': 5
}]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate: true,
store: store,
legend: {
position: 'right'
},
axes: [{
type: 'Numeric',
position: 'left',
fields: ['data', 'data2'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Sample Values',
grid: true,
minimum: 0
}, {
type: 'Category',
position: 'bottom',
fields: ['name'],
title: 'Sample Metrics'
}],
series: [{
type: 'column',
axis: 'left',
highlight: true,
stacked: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function (storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' $');
}
},
label: {
display: 'insideEnd',
'text-anchor': 'middle',
field: 'data',
renderer: Ext.util.Format.numberRenderer('0'),
orientation: 'vertical',
color: '#333'
},
xField: 'name',
yField: ['data', 'data2'],
title: ['Your<b>New</b><br />Label']
}]
});
}
});

How to fetch values of dropdown box on click event in ExTJS

My task is to fetch different types of charts ,when i click from the drop down box.
Based on which graph i select from dropdown ,i need to display the same in JS file.
Currently i can display different types of charts.
Can you please help me how to fetch from based on dropdown values through sencha EXT JS.
Thanks in advance..
please find the attached code below.
/*global Ext:false */
Ext.onReady(function () {
// The data store containing the list of states
var charts = Ext.create('Ext.data.Store', {
fields: [ 'name'],
data: [{
"name": "Bar"
}, {
"name": "Pie"
}, {
"name": "Line"
},{
"name": "Area"
}, {
"name": "Column"
}, {
"name": "Gauge"
}
]
});
// Create the combo box, attached to the charts data store
Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Choose Chart',
store: charts,
queryMode: 'local',
displayField: 'name',
renderTo: Ext.getBody()
});
//Line Chart
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
data: [
{ 'name': 'metric one', 'data1': 10, 'data2': 12, 'data3': 14, 'data4': 8, 'data5': 13 },
{ 'name': 'metric two', 'data1': 7, 'data2': 8, 'data3': 16, 'data4': 10, 'data5': 3 },
{ 'name': 'metric three', 'data1': 5, 'data2': 2, 'data3': 14, 'data4': 12, 'data5': 7 },
{ 'name': 'metric four', 'data1': 2, 'data2': 14, 'data3': 6, 'data4': 1, 'data5': 23 },
{ 'name': 'metric five', 'data1': 4, 'data2': 4, 'data3': 36, 'data4': 13, 'data5': 33 }
]
});
var linechart = Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate: true,
store: store,
axes: [
{
type: 'Numeric',
position: 'left',
fields: ['data1', 'data2'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Sample Values',
grid: true,
minimum: 0
},
{
type: 'Category',
position: 'bottom',
fields: ['name'],
title: 'Sample Metrics'
}
],
series: [
{
type: 'line',
highlight: {
size: 7,
radius: 7
},
axis: 'left',
xField: 'name',
yField: 'data1',
markerConfig: {
type: 'cross',
size: 4,
radius: 4,
'stroke-width': 0
}
},
{
type: 'line',
highlight: {
size: 7,
radius: 7
},
axis: 'left',
fill: true,
xField: 'name',
yField: 'data2',
markerConfig: {
type: 'circle',
size: 4,
radius: 4,
'stroke-width': 0
}
}
]
});
//Bar Chart
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data'],
data: [
{ 'name': 'metric one', 'data':10 },
{ 'name': 'metric two', 'data': 7 },
{ 'name': 'metric three', 'data': 5 },
{ 'name': 'metric four', 'data': 2 },
{ 'name': 'metric five', 'data':27 }
]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate: true,
store: store,
axes: [{
type: 'Numeric',
position: 'bottom',
fields: ['data'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Sample Values',
grid: true,
minimum: 0
}, {
type: 'Category',
position: 'left',
fields: ['name'],
title: 'Sample Metrics'
}],
series: [{
type: 'bar',
axis: 'bottom',
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' views');
}
},
label: {
display: 'insideEnd',
field: 'data',
renderer: Ext.util.Format.numberRenderer('0'),
orientation: 'horizontal',
color: '#333',
'text-anchor': 'middle'
},
xField: 'name',
yField: 'data'
}]
});
//pie chart
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data'],
data: [
{ 'name': 'metric one', 'data': 10 },
{ 'name': 'metric two', 'data': 7 },
{ 'name': 'metric three', 'data': 5 },
{ 'name': 'metric four', 'data': 2 },
{ 'name': 'metric five', 'data': 27 }
]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 350,
animate: true,
store: store,
theme: 'Base:gradients',
series: [{
type: 'pie',
angleField: 'data',
showInLegend: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
// calculate and display percentage on hover
var total = 0;
store.each(function(rec) {
total += rec.get('data');
});
this.setTitle(storeItem.get('name') + ': ' + Math.round(storeItem.get('data') / total * 100) + '%');
}
},
highlight: {
segment: {
margin: 20
}
},
label: {
field: 'name',
display: 'rotate',
contrast: true,
font: '18px Arial'
}
}]
});
//column chart
var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data'],
data: [
{ 'name': 'January', 'data': 10 },
{ 'name': 'February', 'data': 20 },
{ 'name': 'March', 'data': 30},
{ 'name': 'April', 'data': 40 },
{ 'name': 'May', 'data': 50 },
{ 'name': 'June', 'data': 60 },
{ 'name': 'July', 'data': 70 },
{ 'name': 'August', 'data': 60 },
{ 'name': 'September', 'data': 50 },
{ 'name': 'October', 'data': 40},
{ 'name': 'November', 'data': 30},
{ 'name': 'December', 'data': 20}
]
});
Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 1000,
height: 500,
animate: true,
store: store,
axes: [
{
type: 'Numeric',
position: 'left',
fields: ['data'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Sample Values',
grid: true,
minimum: 0
},
{
type: 'Category',
position: 'bottom',
fields: ['name'],
title: 'Sample Metrics'
}
],
series: [
{
type: 'column',
axis: 'left',
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' $');
}
},
label: {
display: 'insideEnd',
'text-anchor': 'middle',
field: 'data',
renderer: Ext.util.Format.numberRenderer('0'),
orientation: 'vertical',
color: '#333'
},
xField: 'name',
yField: 'data'
}
]
});
});
You're going to want to get yourself familiar with the card layout:
For the component to switch views, I feel you're better off using a button with a menu selecting your charts than trying a combo box.
Ext.create('Ext.button.Button', {
text: 'Select Chart',
menu: this.getChartList,
action: 'selectChart',
menuAlign: 'tl-bl'
}]
getChartList: function() {
var menuItems = [];
this.store.each(function(rec) {
mainMenuItems.push({
text: rec.get('name')
});
}
return new Ext.menu.Menu({
items: mainMenuItems
});
}
Then in your controller, or wherever you want to listen to your button:
this.control({
'button[action=selectChart] menuitem': {
click: this.onSelectChartClick,
}
});
onSelectChartClick: function(item) {
switch (item.text) {
case 'Bar':
//logic for showing bar graph
break;
case 'Pie':
//logic for showing pie chart
break;
case 'Line':
//logic for showing line graph
break;
}
}
As for the logic to show the charts, on init you should create a card layout... you could start with a container that holds your items:
this.p = Ext.create('Ext.panel.Panel', {
layout: 'card',
items: [
this.createBarGraph(),
this.createPieChart(),
this.createLineGraph()
]
});
and then on your button listener you can set the active item to your charts:
this.p.getLayout().setActiveItem(this.barGraph);

Ext.js Category axis vertical labels not centered after rotation

Similar to this post in the Sencha forums, how do I get the labels in this (image below) to show up vertically and line up with the grid? Seems like this should be charting basics, but maybe I missed something.
Here is the jsFiddle with the code: http://jsfiddle.net/wilsjd/kg6Ps/8/
Ext.require('Ext.chart.*');
Ext.require(['Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout.container.Fit', 'Ext.window.MessageBox']);
Ext.define('CPI', {
extend: 'Ext.data.Model',
fields: [{
name: 'ReportingPeriod',
type: 'string'
}, {
name: 'PeriodAmount',
type: 'decimal'
}, {
name: 'CumulativeAmount',
type: 'decimal'
}]
});
var store1 = Ext.create('Ext.data.Store', {
model: 'CPI',
data: [{
ReportingPeriod: 'Period1',
PeriodAmount: 1,
CumulativeAmount: 1.2,
Target: 1
}, {
ReportingPeriod: 'Period2',
PeriodAmount: 1.2,
CumulativeAmount: .2,
Target: 1
}, {
ReportingPeriod: 'Period9',
PeriodAmount: 1.5,
CumulativeAmount: 0.8,
Target: 1
}]
});
var chart = Ext.create('Ext.chart.Chart', {
style: 'background:#fff',
animate: true,
theme: 'Category1',
store: store1,
width: 300,
height: 300,
renderTo: 'chart',
axes: [{
type: 'Numeric',
position: 'left',
fields: ['PeriodAmount', 'CumulativeAmount'],
title: 'CPI'
},{
type: 'Category',
position: 'bottom',
fields: ['ReportingPeriod'],
title: 'Reporting Period',
label : {
rotation:{degrees:270}
}
}],
series: [{
type: 'column',
axis: 'left',
xField: 'ReportingPeriod',
yField: 'PeriodAmount',
renderer: function(sprite, record, attr, index, store) {
var value = 0;
if(record.get('PeriodAmount')>=1){
value = 0;
}else{
value = 1;
}
var color = ['rgb(127, 255, 127)',
'rgb(255, 0, 50)'
][value];
return Ext.apply(attr, {
fill: color
});
}
}, {
type: 'line',
axis: 'left',
xField: 'ReportingPeriod',
yField: 'CumulativeAmount',
markerConfig: {
type: 'circle',
size: 4,
radius: 4,
'stroke-width': 0,
}
}]
});
chart.show();
I changed rotation to rotate and it works.
label:{
rotate:{degrees:270}
}
Per usual, the people at sencha's forum are as helpful as a punch to the throat: http://www.sencha.com/forum/showthread.php?156746-line-chart-time-axis-label-rotate-issue&p=678586&viewfull=1#post678586
It appears to be set via dy attribute in the html:
<tspan x="96" dy="3.75">Period1</tspan>
Altering dy will move the h-pos left or right. Unfortunately, there doesn't seem to be an inbuilt way to do it though.
Bottom line: it might be a bug (as a dev mentions in the above link -- but helpfully doesn't expand upon).

Ext.js chart series and axis

Suppose I have some data that I want to display on an Ext.js bar chart and I want my data to revolve around a custom value, "1.0" for example, on the y-axis (versus traditionally "0.0").
Meaning, the picture below has negative values represented with inverted bars, I would like values less than "1.0" to show as an inverted bar on the chart.
Is there a setting that I can set to acheive this? If so, would it be in the series and the axis definition? Maybe the chart itself?
The code for the chart displayed is below:
Ext.require('Ext.chart.*');
Ext.require(['Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout.container.Fit', 'Ext.window.MessageBox']);
Ext.define('CPI', {
extend: 'Ext.data.Model',
fields: [{
name: 'ReportingPeriod',
type: 'string'
}, {
name: 'CPI_P',
type: 'decimal'
}, {
name: 'CPI_C',
type: 'decimal'
}]
});
var store1 = Ext.create('Ext.data.Store', {
model: 'CPI',
data: [{
ReportingPeriod: 'Period1',
CPI_P: '1.9',
CPI_C: '1.2'
}, {
ReportingPeriod: 'Period2',
CPI_P: '1.2',
CPI_C: '1.1'
}, {
ReportingPeriod: 'Period3',
CPI_P: '0.1',
CPI_C: '0.5'
}, {
ReportingPeriod: 'Period4',
CPI_P: '-0.5',
CPI_C: '0.6'
}, {
ReportingPeriod: 'Period5',
CPI_P: '-0.9',
CPI_C: '0.8'
}, {
ReportingPeriod: 'Period6',
CPI_P: '-1.0',
CPI_C: '-0.6'
}, {
ReportingPeriod: 'Period7',
CPI_P: '-1.1',
CPI_C: '-0.7'
}, {
ReportingPeriod: 'Period8',
CPI_P: '-1.5',
CPI_C: '-0.8'
}]
});
var chart = Ext.create('Ext.chart.Chart', {
style: 'background:#fff',
animate: true,
theme: 'Category1',
store: store1,
width: 300,
height: 300,
renderTo: 'chart',
axes: [{
type: 'Numeric',
position: 'left',
fields: ['CPI_P', 'CPI_C'],
title: 'CPI',
grid: true
}, {
type: 'Category',
position: 'bottom',
fields: ['ReportingPeriod'],
title: 'Reporting Period'
}],
series: [{
type: 'column',
axis: 'left',
xField: 'ReportingPeriod',
yField: 'CPI_P',
markerConfig: {
type: 'cross',
size: 3
},
renderer: function(sprite, record, attr, index, store) {
var value = (record.get('CPI_P') >> 2) % 2;
var color = ['rgb(213, 70, 121)',
'rgb(44, 153, 201)'
][value];
return Ext.apply(attr, {
fill: color
});
}
}]
});
chart.show();
UPDATE
If I add a minimum to y-axis I get closer (sort of)
...
axes: [{
type: 'Numeric',
position: 'left',
fields: ['CPI_P', 'CPI_C'],
title: 'CPI',
grid: true,
minimum: 1,
}....
It's the right idea, because the bars now are relevant to the number 1, but I obviously need to keep the bars on the graph.
What has seemed to work is subtracting 1 from my data and adding 1 to the labels.
axes: [{
type: 'Numeric',
position: 'left',
grid: true,
maximum: 1.0, //will render to 2.0
fields: ['PeriodAmount', 'CumulativeAmount'],
label:{
renderer:function(v){
return (v+1).toFixed(2);
}
}
}...]
This is a viable work around for me, but I wouldn't consider this an elegant answer since it isn't very configurable for custom values. For example, changing this to -1 or 2 would require more work than just changing a simple setting.

Resources