I have to plot (something like) a rotated parabola using extjs charts (version 4.2.10).
I should draw something like this (just the curve):
But at best I can get is this (on jsfiddle).
var chartDataStore = Ext.create("Ext.data.ArrayStore", {
storeId: "chartData",
fields: [
{ name: "x", type: "integer" },
{ name: "y", type: "integer" }
],
data: [
[10,14],
[5,10],
[2,6.3],
[0,2],
[2,1],
[5,2]
]
});
var win = Ext.create("Ext.chart.Chart", {
width: 600,
height: 400,
hidden: false,
title: "Example chart",
renderTo: "demoChart",
layout: "fit",
style: "background:#fff",
animate: true,
store: chartDataStore,
shadow: true,
theme: "Category1",
legend: {
position: "bottom"
},
axes: [{
type: "Numeric",
minimum: 0,
position: "left",
fields: ["y"],
title: "Y",
minorTickSteps: 1,
grid: {
odd: {
opacity: 1,
fill: "#ddd",
stroke: "#bbb",
"stroke-width": 0.5
}
}
}, {
type: "Category",
position: "bottom",
fields: ["x"],
title: "X"
}],
series: [{
type: "line",
highlight: {
size: 7,
radius: 7
},
axis: "left",
smooth: true,
xField: "x",
yField: "y",
title: "Rotated Parabola (not working)",
markerConfig: {
type: "cross",
size: 4,
radius: 4,
"stroke-width": 0
},
}]
});
A collegue of mine suggested to use Highchart for ExtJS but we were not able to draw such plot. Note that the solution should run on IE9.
Any suggestion?
The problem here is that such curve has two values of y to one value of x and that cannot be achieved with line chart.
One possibility would be to draw a straight parabola with Ext chart and then rotate the whole chart with css transform.
Related
I have to display a bar chart which has mixed data in the store with negative and positive values to be shown on y-axis. I want to display the chart like in this image: https://assets.highcharts.com/images/demo-thumbnails/highcharts/column-negative-default.png
var store = Ext.create('Ext.data.Store', {
fields: ['name','someField'],
data: [{
"name": "A",
"someField": -21414
}, {
"name": "B",
"someField": 22034
}, {
"name": "C",
"someField": -16270
}, {
"name": "D",
"someField": 20838
}, {
"name": "X",
"someField": 2720
}]
})
Ext.create('Ext.panel.Panel', {
items: [{
xtype: 'cartesian',
width: '100%',
height: 500,
store: store,
insetPadding: 40,
innerPadding: {
left: 40,
right: 40
},
axes: [{
type: 'numeric',
fields: 'someField',
position: 'left'
}, {
type: 'string',
fields: 'name',
position: 'bottom',
}],
series: [{
type: 'bar',
xField: 'name',
yField: 'someField',
}]
}]
});
The origin should be at 0.
I tried using postion:'radial' in place of 'bottom', but, using this removes the x-axis and also the labels are not seen.
How can I reverse the y-axis values so that they can be flipped below x-axis(upside down)?
I have a requirement in my application to create a line chart with multiple series. The problem is all the series starts from the same year. My requirement is to create a chart just like the example given at: jsfiddle.net/pyrliu/JPEEv/2/
var chartDataStore = Ext.create("Ext.data.ArrayStore", {
storeId: "chartData",
fields: [
{ name: "year", type: "integer" },
"country1",
{ name: "value1", type: "integer" },
"country2",
{ name: "value2", type: "integer" }
],
data: [
[1997,"USA",66,"Canada",53],
[1998,"USA",81,"Canada",67],
[1999,"USA",83,"Canada",46],
[2000,"USA",61,"Canada",45],
[2001,"USA",67,"Canada",53],
[2002,"USA",68,"Canada",43]
]
});
var win = Ext.create("Ext.chart.Chart", {
width: 600,
height: 400,
hidden: false,
title: "Example working chart",
renderTo: "demoChart",
layout: "fit",
style: "background:#fff",
animate: true,
store: chartDataStore,
shadow: true,
theme: "Category1",
legend: {
position: "bottom"
},
axes: [{
type: "Numeric",
minimum: 0,
position: "left",
fields: ["value1", "value2"],
title: "Value",
minorTickSteps: 1,
grid: {
odd: {
opacity: 1,
fill: "#ddd",
stroke: "#bbb",
"stroke-width": 0.5
}
}
}, {
type: "Category",
position: "bottom",
fields: ["year"],
title: "Year"
}],
series: [{
type: "line",
highlight: {
size: 7,
radius: 7
},
axis: "left",
smooth: true,
xField: "year",
yField: "value1",
title: "USA",
markerConfig: {
type: "cross",
size: 4,
radius: 4,
"stroke-width": 0
},
}, {
type: "line",
highlight: {
size: 7,
radius: 7
},
axis: "left",
smooth: true,
xField: "year",
yField: "value2",
title: "Canada",
markerConfig: {
type: "circle",
size: 4,
radius: 4,
"stroke-width": 0
}
}]
});
In the above example there are two series for USA and Canada. I need the data for Canada to be shown from year 2009. In the above example the data is from year 1997. I need one series to start from 1999 and the other from 1997. how to skip two values from the same store?
Are you looking for something like this jsFiddle? It's all in how your data is treated, and you need to treat null values as null values, not 0s, so that's where the convert function comes in to play. Props go to this SO answer.
// This is the juice to fix the problem
function convertInt(value) {
if (typeof value !== 'number') // or other similar conversion
return undefined;
return value;
}
var chartDataStore = Ext.create("Ext.data.ArrayStore", {
storeId: "chartData",
fields: [
{name: "year", type: "integer"},
"country1",
{name: "value1", type: "integer", convert: convertInt},
"country2",
{name: "value2", type: "integer", convert: convertInt}
],
data: [
[1997, "USA", 66, "Canada", null],
[1998, "USA", 81, "Canada", null],
[1999, "USA", 83, "Canada", 46],
[2000, "USA", 61, "Canada", 45],
[2001, "USA", null, "Canada", 53],
[2002, "USA", null, "Canada", 43]
]
});
var win = Ext.create("Ext.chart.Chart", {
width: 600,
height: 400,
hidden: false,
title: "Example working chart",
renderTo: "demoChart",
layout: "fit",
style: "background:#fff",
animate: true,
store: chartDataStore,
shadow: true,
theme: "Category1",
legend: {
position: "bottom"
},
axes: [{
type: "Numeric",
minimum: 0,
position: "left",
fields: ["value1", "value2"],
title: "Value",
minorTickSteps: 1,
grid: {
odd: {
opacity: 1,
fill: "#ddd",
stroke: "#bbb",
"stroke-width": 0.5
}
}
}, {
type: "Category",
position: "bottom",
fields: ["year"],
title: "Year"
}],
series: [{
type: "line",
highlight: {
size: 7,
radius: 7
},
axis: "left",
smooth: true,
xField: "year",
yField: "value1",
title: "USA",
markerConfig: {
type: "cross",
size: 4,
radius: 4,
"stroke-width": 0
},
}, {
type: "line",
highlight: {
size: 7,
radius: 7
},
axis: "left",
smooth: true,
xField: "year",
yField: "value2",
title: "Canada",
markerConfig: {
type: "circle",
size: 4,
radius: 4,
"stroke-width": 0
}
}]
});
Currently I am rendering single line chart using json data which is as follow :
{"eventType":"A","startOpen":"0","asOfDate":"21-OCT-13","intervalNo":0},
{"eventType":"A","startOpen":"47","asOfDate":"21-OCT-13","intervalNo":1},
{"eventType":"A","startOpen":"60","asOfDate":"21-OCT-13","intervalNo":2},
{"eventType":"B","startOpen":"79","asOfDate":"21-OCT-13","intervalNo":4},
{"eventType":"B","startOpen":"90","asOfDate":"21-OCT-13","intervalNo":6}
I am plotting graph startOpen against intervalNo. Now I want to plot the graph using grouping on eventType field. Means for above data two line should be drawn in single chart, one for eventType A and another for eventType B.
Appreciate your any kind of help. Thank you :)
My current code for chart :
Ext.define("TestBug.view.TrendsChart", {
extend: "Ext.chart.Chart",
alias: "widget.trendschart",
store: "Trends",
style: 'background:#fff',
animate: true,
shadow: true,
groupField:'eventType',
legend: {position: 'right'},
axes: [
{
type: "numeric",
position: "left",
fields: "intervalNo",
title:"Interval No",
grid: {
odd: {
opacity: 1,
fill: '#ddd',
stroke: '#bbb',
'stroke-width': 0.5
}
}
},
{
type: "numeric",
position: "bottom",
fields: "startOpen",
title: 'Start Open'
}
],
series: [
{
type: "line",
axis: "left",
xField: "startOpen",
yField: "intervalNo",
gField:'eventType',
markerConfig: {
type: 'circle',
size: 4,
radius: 4,
'stroke-width': 0
}
}
]
});
In order to plot multiple lines width different x values, you have to use multiple line series. Value points with value of undefined will be skipped, that is they won't be drawn in the chart.
Here's how to adapt your example data to do that (fiddle):
Ext.define("TestBug.view.TrendsChart", {
extend: "Ext.chart.Chart",
alias: "widget.trendschart",
store: {
fields: [
'eventType',
{name: 'startOpen', type: 'int'},
'asOfDate',
'intervalA',
'intervalB'
]
,data: [
{"eventType":"A","startOpen":"0","intervalA":0,"intervalB":undefined},
{"eventType":"A","startOpen":"47","intervalA":1,"intervalB":undefined},
{"eventType":"A","startOpen":"35","intervalA":undefined,"intervalB":2},
{"eventType":"B","startOpen":"79","intervalA":undefined,"intervalB":4},
{"eventType":"B","startOpen":"90","intervalA":undefined,"intervalB":6}
]
},
style: 'background:#fff',
animate: true,
shadow: true,
groupField: 'eventType',
legend: {
position: 'right'
},
axes: [{
type: "numeric",
position: "left",
fields: ["intervalA", "intervalB"],
title: "Interval No",
grid: {
odd: {
opacity: 1,
fill: '#ddd',
stroke: '#bbb',
'stroke-width': 0.5
}
}
},{
type: "numeric",
position: "bottom",
fields: "startOpen",
title: 'Start Open'
}],
series: [{
type: "line",
axis: "left",
xField: "startOpen",
yField: "intervalA",
title: "A"
},{
type: "line",
axis: 'left',
xField: 'startOpen',
yField: 'intervalB',
title: "B"
}]
});
Ext.widget('trendschart', {
renderTo: Ext.getBody()
,width: 600
,height: 300
});
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).
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.