Code:
Ext.define('Ext.chart.series.KPIGauge', {
extend: 'Ext.chart.series.Gauge',
alias: 'series.kpigauge',
type: "kpigauge",
rad: Math.PI / 180,
config: {
/**
* @cfg {String} angleField
* The store record field name to be used for the gauge angles.
* The values bound to this field name must be positive real numbers.
* This parameter is required.
*/
angleField: false,
ranges: [],
/**
* @cfg {Boolean} needle
* Use the Gauge Series as an area series or add a needle to it. Default's false.
*/
needle: false,
/**
* @cfg {Boolean/Number} donut
* Use the entire disk or just a fraction of it for the gauge. Default's false.
*/
donut: false,
/**
* @cfg {Boolean} showInLegend
* Whether to add the gauge chart elements as legend items. Default's false.
*/
showInLegend: false,
/**
* @cfg {Object} style
* An object containing styles for overriding series styles from Theming.
*/
minimum: 0,
maximum: 100,
colorSet: []
},
drawSeries: function () {
var me = this,
chart = me.getChart(),
store = chart.substore || chart.getStore(),
group = me.group,
animate = me.getChart().getAnimate(),
axis = me.getChart().getAxes().get(0),
minimum = axis && axis.getMinimum() || me.getMinimum() || 0,
maximum = axis && axis.getMaximum() || me.getMaximum() || 0,
ranges = me.getRanges(),
field = me.getAngleField() || me.field,
surface = me.getSurface(),
chartBBox = chart.chartBBox,
// rad = me.rad,
donut = +me.getDonut(),
values = {},
items = [],
seriesStyle = me.style,
colors = chart.getColorsStyle(),
colorArrayLength = colors && colors.length || 0,
cos = Math.cos,
sin = Math.sin,
enableShadows = !!chart.getShadow(),
rendererAttributes, centerX, centerY, slice, slices, sprite, value,
item, ln, record, i, j, r, slice, splitAngle, rl, startAngle, endAngle, middleAngle, sliceLength, path,
p, spriteOptions, bbox, valueAngle;
if (ranges == undefined || ranges.length <= 0) {
console.log(':((((');
}
else {
console.log('Hurrey!!!');
}
if (me.fireEvent('beforedraw', me) === false) {
return;
}
Ext.chart.series.Gauge.superclass.drawSeries.call(this);
me.setBBox();
bbox = me.bbox;
//override theme colors
if (me.getColorSet()) {
colors = me.getColorSet();
colorArrayLength = colors.length;
}
//if not store or store is empty then there's nothing to draw
if (!me.getRecordCount()) {
surface.getItems().hide(true);
return;
}
centerX = me.centerX = (chartBBox.width / 2);
centerY = me.centerY = chartBBox.height;
me.radius = Math.min(centerX, centerY);
me.slices = slices = [];
me.items = items = [];
if (!me.value) {
record = store.getAt(0);
me.value = record.get(field);
}
value = me.value;
valueAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
for (r = 0, rl = ranges.length; r < rl; r++) {
splitFromAngle = -180 * (1 - (ranges[r].from - minimum) / (maximum - minimum));
splitToAngle = -180 * (1 - (ranges[r].to - minimum) / (maximum - minimum));
slices.push({
series: me,
startAngle: splitFromAngle,
endAngle: splitToAngle,
rho: me.radius,
value: value,
color: ranges[r].color
});
}
//do pie slices after.
for (i = 0, ln = slices.length; i < ln; i++) {
slice = slices[i];
sprite = group.getAt(i);
//set pie slice properties
rendererAttributes = Ext.apply({
segment: {
startAngle: slice.startAngle,
endAngle: slice.endAngle,
margin: 0,
rho: slice.rho,
startRho: slice.rho * +donut / 100,
endRho: slice.rho
}
}, Ext.apply(seriesStyle, colors && { fill: colors[i % colorArrayLength]} || {}));
item = Ext.apply({},
rendererAttributes.segment, {
slice: slice,
series: me,
storeItem: record,
index: i
});
items[i] = item;
// Create a new sprite if needed (no height)
if (!sprite) {
spriteOptions = Ext.apply({
type: "path",
group: group
}, Ext.apply(seriesStyle, colors && { fill: colors[i % colorArrayLength]} || {}));
if (enableShadows) {
Ext.apply(spriteOptions, me.getShadowOptions());
}
sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
}
slice.sprite = slice.sprite || [];
item.sprite = sprite;
slice.sprite.push(sprite);
if (animate) {
rendererAttributes = me.getRenderer()(sprite, record, rendererAttributes, i, store);
sprite._to = rendererAttributes;
me.onAnimate(sprite, {
to: rendererAttributes
});
} else {
rendererAttributes = me.getRenderer()(sprite, record, Ext.apply(rendererAttributes, {
hidden: false
}), i, store);
sprite.setAttributes(rendererAttributes, true);
}
}
valueAngle = valueAngle * Math.PI / 180;
if (!me.needleSprite) {
me.needleSprite = me.getSurface().add({
type: 'path',
path: ['M', centerX + (me.radius * +donut / 100) * cos(valueAngle),
centerY + -Math.abs((me.radius * +donut / 100) * sin(valueAngle)),
'L', centerX + me.radius * cos(valueAngle),
centerY + -Math.abs(me.radius * sin(valueAngle))],
'stroke-width': 4,
'stroke': '#222'
});
} else {
if (animate) {
me.onAnimate(me.needleSprite, {
to: {
path: ['M', centerX + (me.radius * 0 / 100) * cos(valueAngle),
centerY + -Math.abs((me.radius * 0 / 100) * sin(valueAngle)),
'L', centerX + me.radius * cos(valueAngle),
centerY + -Math.abs(me.radius * sin(valueAngle))]
}
});
} else {
me.needleSprite.setAttributes({
type: 'path',
path: ['M', centerX + (me.radius * 0 / 100) * cos(valueAngle),
centerY + -Math.abs((me.radius * 0 / 100) * sin(valueAngle)),
'L', centerX + me.radius * cos(valueAngle),
centerY + -Math.abs(me.radius * sin(valueAngle))]
});
}
}
me.needleSprite.setAttributes({
hidden: false
}, true);
delete me.value;
me.fireEvent('draw', me);
}
});
and if i replace the existing gaugeChart drawseries function, it is working fine.
Code:
Ext.define('Ext.chart.series.Gauge', {
extend: 'Ext.chart.series.Series',
type: "gauge",
rad: Math.PI / 180,
config: {
/**
* @cfg {String} angleField
* The store record field name to be used for the gauge angles.
* The values bound to this field name must be positive real numbers.
* This parameter is required.
*/
angleField: false,
ranges: [],
/**
* @cfg {Boolean} needle
* Use the Gauge Series as an area series or add a needle to it. Default's false.
*/
needle: false,
/**
* @cfg {Boolean/Number} donut
* Use the entire disk or just a fraction of it for the gauge. Default's false.
*/
donut: false,
/**
* @cfg {Boolean} showInLegend
* Whether to add the gauge chart elements as legend items. Default's false.
*/
showInLegend: false,
/**
* @cfg {Object} style
* An object containing styles for overriding series styles from Theming.
*/
minimum: 0,
maximum: 100,
colorSet: []
},
constructor: function (config) {
if (!config.angleField && config.field) {
console.warn('use angleField instead');
config.angleField = config.field;
}
this.callParent(arguments);
var me = this,
chart = me.getChart(),
surface = me.getSurface();
surface.addCustomAttribute("segment", function (opt) {
return me.getSegment(opt);
});
},
//@private updates some onbefore render parameters.
initialize: function () {
var me = this;
me.callParent();
},
// @private returns an object with properties for a PieSlice.
getSegment: function (opt) {
var me = this,
rad = me.rad,
cos = Math.cos,
sin = Math.sin,
abs = Math.abs,
x = me.centerX,
y = me.centerY,
x1 = 0, x2 = 0, x3 = 0, x4 = 0,
y1 = 0, y2 = 0, y3 = 0, y4 = 0,
delta = 1e-2,
startAngle = opt.startAngle,
endAngle = opt.endAngle,
midAngle = (startAngle + endAngle) / 2 * rad,
margin = opt.margin || 0,
flag = abs(endAngle - startAngle) > 180,
auxValue = abs(endAngle % 360),
flag2 = auxValue > 90 && auxValue < 270,
a1 = Math.min(startAngle, endAngle) * rad,
a2 = Math.max(startAngle, endAngle) * rad,
singleSlice = false,
fullCircle = false;
x += margin * cos(midAngle);
y += margin * sin(midAngle);
x1 = x + opt.startRho * cos(a1);
y1 = y + opt.startRho * sin(a1);
x2 = x + opt.endRho * cos(a1);
y2 = y + opt.endRho * sin(a1);
x3 = x + opt.startRho * cos(a2);
y3 = y + opt.startRho * sin(a2);
x4 = x + opt.endRho * cos(a2);
y4 = y + opt.endRho * sin(a2);
if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
singleSlice = true;
}
fullCircle = singleSlice && (abs(x2 - x4) <= delta && abs(y2 - y4) <= delta);
//Solves mysterious clipping bug with IE
if (fullCircle) {
return {
path: [
["M", x4, y4 - 1e-4],
["A", opt.endRho, opt.endRho, 0, +flag, +flag2, x4, y4],
["Z"]]
};
} else if (singleSlice) {
return {
path: [
["M", x1, y1],
["L", x2, y2],
["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
["Z"]]
};
} else {
return {
path: [
["M", x1, y1],
["L", x2, y2],
["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
["M", x4, y4],
["L", x3, y3],
["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
["Z"]]
};
}
},
// @private utility function to calculate the middle point of a pie slice.
calcMiddle: function (item) {
var me = this,
rad = me.rad,
slice = item.slice,
x = me.centerX,
y = me.centerY,
startAngle = slice.startAngle,
endAngle = slice.endAngle,
a1 = Math.min(startAngle, endAngle) * rad,
a2 = Math.max(startAngle, endAngle) * rad,
midAngle = -(a1 + (a2 - a1) / 2),
xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
item.middle = {
x: xm,
y: ym
};
},
drawSeries: function () {
var me = this,
chart = me.getChart(),
store = chart.substore || chart.getStore(),
group = me.group,
animate = me.getChart().getAnimate(),
axis = me.getChart().getAxes().get(0),
minimum = axis && axis.getMinimum() || me.getMinimum() || 0,
maximum = axis && axis.getMaximum() || me.getMaximum() || 0,
ranges = me.getRanges(),
field = me.getAngleField() || me.field,
surface = me.getSurface(),
chartBBox = chart.chartBBox,
// rad = me.rad,
donut = +me.getDonut(),
values = {},
items = [],
seriesStyle = me.style,
colors = chart.getColorsStyle(),
colorArrayLength = colors && colors.length || 0,
cos = Math.cos,
sin = Math.sin,
enableShadows = !!chart.getShadow(),
rendererAttributes, centerX, centerY, slice, slices, sprite, value,
item, ln, record, i, j, r, slice, splitAngle, rl, startAngle, endAngle, middleAngle, sliceLength, path,
p, spriteOptions, bbox, valueAngle;
if (ranges == undefined || ranges.length <= 0) {
console.log(':((((');
}
else {
console.log('Hurrey!!!');
}
if (me.fireEvent('beforedraw', me) === false) {
return;
}
Ext.chart.series.Gauge.superclass.drawSeries.call(this);
me.setBBox();
bbox = me.bbox;
//override theme colors
if (me.getColorSet()) {
colors = me.getColorSet();
colorArrayLength = colors.length;
}
//if not store or store is empty then there's nothing to draw
if (!me.getRecordCount()) {
surface.getItems().hide(true);
return;
}
centerX = me.centerX = (chartBBox.width / 2);
centerY = me.centerY = chartBBox.height;
me.radius = Math.min(centerX, centerY);
me.slices = slices = [];
me.items = items = [];
if (!me.value) {
record = store.getAt(0);
me.value = record.get(field);
}
value = me.value;
valueAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
for (r = 0, rl = ranges.length; r < rl; r++) {
splitFromAngle = -180 * (1 - (ranges[r].from - minimum) / (maximum - minimum));
splitToAngle = -180 * (1 - (ranges[r].to - minimum) / (maximum - minimum));
slices.push({
series: me,
startAngle: splitFromAngle,
endAngle: splitToAngle,
rho: me.radius,
value: value,
color: ranges[r].color
});
}
//do pie slices after.
for (i = 0, ln = slices.length; i < ln; i++) {
slice = slices[i];
sprite = group.getAt(i);
//set pie slice properties
rendererAttributes = Ext.apply({
segment: {
startAngle: slice.startAngle,
endAngle: slice.endAngle,
margin: 0,
rho: slice.rho,
startRho: slice.rho * +donut / 100,
endRho: slice.rho
}
}, Ext.apply(seriesStyle, colors && { fill: colors[i % colorArrayLength]} || {}));
item = Ext.apply({},
rendererAttributes.segment, {
slice: slice,
series: me,
storeItem: record,
index: i
});
items[i] = item;
// Create a new sprite if needed (no height)
if (!sprite) {
spriteOptions = Ext.apply({
type: "path",
group: group
}, Ext.apply(seriesStyle, colors && { fill: colors[i % colorArrayLength]} || {}));
if (enableShadows) {
Ext.apply(spriteOptions, me.getShadowOptions());
}
sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
}
slice.sprite = slice.sprite || [];
item.sprite = sprite;
slice.sprite.push(sprite);
if (animate) {
rendererAttributes = me.getRenderer()(sprite, record, rendererAttributes, i, store);
sprite._to = rendererAttributes;
me.onAnimate(sprite, {
to: rendererAttributes
});
} else {
rendererAttributes = me.getRenderer()(sprite, record, Ext.apply(rendererAttributes, {
hidden: false
}), i, store);
sprite.setAttributes(rendererAttributes, true);
}
}
valueAngle = valueAngle * Math.PI / 180;
if (!me.needleSprite) {
me.needleSprite = me.getSurface().add({
type: 'path',
path: ['M', centerX + (me.radius * +donut / 100) * cos(valueAngle),
centerY + -Math.abs((me.radius * +donut / 100) * sin(valueAngle)),
'L', centerX + me.radius * cos(valueAngle),
centerY + -Math.abs(me.radius * sin(valueAngle))],
'stroke-width': 4,
'stroke': '#222'
});
} else {
if (animate) {
me.onAnimate(me.needleSprite, {
to: {
path: ['M', centerX + (me.radius * 0 / 100) * cos(valueAngle),
centerY + -Math.abs((me.radius * 0 / 100) * sin(valueAngle)),
'L', centerX + me.radius * cos(valueAngle),
centerY + -Math.abs(me.radius * sin(valueAngle))]
}
});
} else {
me.needleSprite.setAttributes({
type: 'path',
path: ['M', centerX + (me.radius * 0 / 100) * cos(valueAngle),
centerY + -Math.abs((me.radius * 0 / 100) * sin(valueAngle)),
'L', centerX + me.radius * cos(valueAngle),
centerY + -Math.abs(me.radius * sin(valueAngle))]
});
}
}
me.needleSprite.setAttributes({
hidden: false
}, true);
delete me.value;
me.fireEvent('draw', me);
},
/**
* Sets the Gauge chart to the current specified value.
*/
setValue: function (value) {
this.value = value;
this.drawSeries();
},
// @private callback for when creating a label sprite.
onCreateLabel: Ext.emptyFn,
// @private callback for when placing a label sprite.
onPlaceLabel: Ext.emptyFn,
// @private callback for when placing a callout.
onPlaceCallout: Ext.emptyFn,
// @private handles sprite animation for the series.
onAnimate: function (sprite, attr) {
sprite.show();
Ext.chart.series.Gauge.superclass.onAnimate.apply(this, arguments);
},
isItemInPoint: function () {
return false;
},
// @private shows all elements in the series.
showAll: function () {
if (!isNaN(this._index)) {
this.getExcludes()[this._index] = false;
this.drawSeries();
}
},
/**
* Returns the color of the series (to be displayed as color for the series legend item).
* @param index {Number} Info about the item; same format as returned by #getItemForPoint
*/
getLegendColor: function (index) {
var me = this,
colors = me.getChart().getColorsStyle();
return me.getColorFromStyle(colors[index % colors.length]);
}
});