-<!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-chart.series.Gauge'>/**
-</span> * @class Ext.chart.series.Gauge
- * @extends Ext.chart.series.Series
- *
- * Creates a Gauge Chart. Gauge Charts are used to show progress in a certain variable. There are two ways of using the Gauge chart.
- * One is setting a store element into the Gauge and selecting the field to be used from that store. Another one is instanciating the
- * visualization and using the `setValue` method to adjust the value you want.
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <title>The source code</title>
+ <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
+ <script type="text/javascript" src="../prettify/prettify.js"></script>
+ <style type="text/css">
+ .highlight { display: block; background-color: #ddd; }
+ </style>
+ <script type="text/javascript">
+ function highlight() {
+ document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
+ }
+ </script>
+</head>
+<body onload="prettyPrint(); highlight();">
+ <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Gauge'>/**
+</span> * @class Ext.chart.axis.Gauge
+ * @extends Ext.chart.axis.Abstract
+ *
+ * Gauge Axis is the axis to be used with a Gauge series. The Gauge axis
+ * displays numeric data from an interval defined by the `minimum`, `maximum` and
+ * `step` configuration properties. The placement of the numeric data can be changed
+ * by altering the `margin` option that is set to `10` by default.
+ *
+ * A possible configuration for this axis would look like:
*
- * A chart/series configuration for the Gauge visualization could look like this:
- *
- * {
- * xtype: 'chart',
- * store: store,
- * axes: [{
- * type: 'gauge',
- * position: 'gauge',
- * minimum: 0,
- * maximum: 100,
- * steps: 10,
- * margin: -10
- * }],
- * series: [{
- * type: 'gauge',
- * field: 'data1',
- * donut: false,
- * colorSet: ['#F49D10', '#ddd']
- * }]
- * }
- *
- * In this configuration we create a special Gauge axis to be used with the gauge visualization (describing half-circle markers), and also we're
- * setting a maximum, minimum and steps configuration options into the axis. The Gauge series configuration contains the store field to be bound to
- * the visual display and the color set to be used with the visualization.
- *
- * @xtype gauge
+ * axes: [{
+ * type: 'gauge',
+ * position: 'gauge',
+ * minimum: 0,
+ * maximum: 100,
+ * steps: 10,
+ * margin: 7
+ * }],
*/
-Ext.define('Ext.chart.series.Gauge', {
+Ext.define('Ext.chart.axis.Gauge', {
/* Begin Definitions */
- extend: 'Ext.chart.series.Series',
+ extend: 'Ext.chart.axis.Abstract',
/* End Definitions */
-
- type: "gauge",
- alias: 'series.gauge',
-
- rad: Math.PI / 180,
-
-<span id='Ext-chart.series.Gauge-cfg-highlightDuration'> /**
-</span> * @cfg {Number} highlightDuration
- * The duration for the pie slice highlight effect.
+
+<span id='Ext-chart-axis-Gauge-cfg-minimum'> /**
+</span> * @cfg {Number} minimum (required) the minimum value of the interval to be displayed in the axis.
*/
- highlightDuration: 150,
-<span id='Ext-chart.series.Gauge-cfg-angleField'> /**
-</span> * @cfg {String} angleField
- * The store record field name to be used for the pie angles.
- * The values bound to this field name must be positive real numbers.
- * This parameter is required.
+<span id='Ext-chart-axis-Gauge-cfg-maximum'> /**
+</span> * @cfg {Number} maximum (required) the maximum value of the interval to be displayed in the axis.
*/
- angleField: false,
-<span id='Ext-chart.series.Gauge-cfg-needle'> /**
-</span> * @cfg {Boolean} needle
- * Use the Gauge Series as an area series or add a needle to it. Default's false.
- */
- needle: false,
-
-<span id='Ext-chart.series.Gauge-cfg-donut'> /**
-</span> * @cfg {Boolean|Number} donut
- * Use the entire disk or just a fraction of it for the gauge. Default's false.
+<span id='Ext-chart-axis-Gauge-cfg-steps'> /**
+</span> * @cfg {Number} steps (required) the number of steps and tick marks to add to the interval.
*/
- donut: false,
-<span id='Ext-chart.series.Gauge-cfg-showInLegend'> /**
-</span> * @cfg {Boolean} showInLegend
- * Whether to add the pie chart elements as legend items. Default's false.
+<span id='Ext-chart-axis-Gauge-cfg-margin'> /**
+</span> * @cfg {Number} margin (optional) the offset positioning of the tick marks and labels in pixels. Default's 10.
*/
- showInLegend: false,
-<span id='Ext-chart.series.Gauge-cfg-style'> /**
-</span> * @cfg {Object} style
- * An object containing styles for overriding series styles from Theming.
- */
- style: {},
-
- constructor: function(config) {
- this.callParent(arguments);
- var me = this,
- chart = me.chart,
+ position: 'gauge',
+
+ alias: 'axis.gauge',
+
+ drawAxis: function(init) {
+ var chart = this.chart,
surface = chart.surface,
- store = chart.store,
- shadow = chart.shadow, i, l, cfg;
- Ext.apply(me, config, {
- shadowAttributes: [{
- "stroke-width": 6,
- "stroke-opacity": 1,
- stroke: 'rgb(200, 200, 200)',
- translate: {
- x: 1.2,
- y: 2
- }
- },
- {
- "stroke-width": 4,
- "stroke-opacity": 1,
- stroke: 'rgb(150, 150, 150)',
- translate: {
- x: 0.9,
- y: 1.5
+ bbox = chart.chartBBox,
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + bbox.height,
+ margin = this.margin || 10,
+ rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
+ sprites = [], sprite,
+ steps = this.steps,
+ i, pi = Math.PI,
+ cos = Math.cos,
+ sin = Math.sin;
+
+ if (this.sprites && !chart.resizing) {
+ this.drawLabel();
+ return;
+ }
+
+ if (this.margin >= 0) {
+ if (!this.sprites) {
+ //draw circles
+ for (i = 0; i <= steps; i++) {
+ sprite = surface.add({
+ type: 'path',
+ path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+ centerY + (rho - margin) * sin(i / steps * pi - pi),
+ 'L', centerX + rho * cos(i / steps * pi - pi),
+ centerY + rho * sin(i / steps * pi - pi), 'Z'],
+ stroke: '#ccc'
+ });
+ sprite.setAttributes({
+ hidden: false
+ }, true);
+ sprites.push(sprite);
}
- },
- {
- "stroke-width": 2,
- "stroke-opacity": 1,
- stroke: 'rgb(100, 100, 100)',
- translate: {
- x: 0.6,
- y: 1
+ } else {
+ sprites = this.sprites;
+ //draw circles
+ for (i = 0; i <= steps; i++) {
+ sprites[i].setAttributes({
+ path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+ centerY + (rho - margin) * sin(i / steps * pi - pi),
+ 'L', centerX + rho * cos(i / steps * pi - pi),
+ centerY + rho * sin(i / steps * pi - pi), 'Z'],
+ stroke: '#ccc'
+ }, true);
}
- }]
- });
- me.group = surface.getGroup(me.seriesId);
- if (shadow) {
- for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
- me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
}
}
- surface.customAttributes.segment = function(opt) {
- return me.getSegment(opt);
- };
- },
-
- //@private updates some onbefore render parameters.
- initialize: function() {
- var me = this,
- store = me.chart.substore || me.chart.store;
- //Add yFields to be used in Legend.js
- me.yField = [];
- if (me.label.field) {
- store.each(function(rec) {
- me.yField.push(rec.get(me.label.field));
- });
+ this.sprites = sprites;
+ this.drawLabel();
+ if (this.title) {
+ this.drawTitle();
}
},
-
- // @private returns an object with properties for a Slice
- getSegment: function(opt) {
+
+ drawTitle: function() {
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,
- r = opt.endRho - opt.startRho,
- startAngle = opt.startAngle,
- endAngle = opt.endAngle,
- midAngle = (startAngle + endAngle) / 2 * rad,
- margin = opt.margin || 0,
- flag = abs(endAngle - startAngle) > 180,
- a1 = Math.min(startAngle, endAngle) * rad,
- a2 = Math.max(startAngle, endAngle) * rad,
- singleSlice = 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;
- }
- //Solves mysterious clipping bug with IE
- 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],
- ["L", x3, y3],
- ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
- ["Z"]]
- };
+ chart = me.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ labelSprite = me.titleSprite,
+ labelBBox;
+
+ if (!labelSprite) {
+ me.titleSprite = labelSprite = surface.add({
+ type: 'text',
+ zIndex: 2
+ });
}
+ labelSprite.setAttributes(Ext.apply({
+ text: me.title
+ }, me.label || {}), true);
+ labelBBox = labelSprite.getBBox();
+ labelSprite.setAttributes({
+ x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
+ y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
+ }, true);
},
- // @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,
- radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
- donut = +me.donut,
- 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
- };
+<span id='Ext-chart-axis-Gauge-method-setTitle'> /**
+</span> * Updates the {@link #title} of this axis.
+ * @param {String} title
+ */
+ setTitle: function(title) {
+ this.title = title;
+ this.drawTitle();
},
-<span id='Ext-chart.series.Gauge-method-drawSeries'> /**
-</span> * Draws the series for the current chart.
- */
- drawSeries: function() {
- var me = this,
- chart = me.chart,
- store = chart.substore || chart.store,
- group = me.group,
- animate = me.chart.animate,
- axis = me.chart.axes.get(0),
- minimum = axis && axis.minimum || me.minimum || 0,
- maximum = axis && axis.maximum || me.maximum || 0,
- field = me.angleField || me.field || me.xField,
+ drawLabel: function() {
+ var chart = this.chart,
surface = chart.surface,
- chartBBox = chart.chartBBox,
- rad = me.rad,
- donut = +me.donut,
- values = {},
- items = [],
- seriesStyle = me.seriesStyle,
- seriesLabelStyle = me.seriesLabelStyle,
- colorArrayStyle = me.colorArrayStyle,
- colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
- gutterX = chart.maxGutter[0],
- gutterY = chart.maxGutter[1],
+ bbox = chart.chartBBox,
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + bbox.height,
+ margin = this.margin || 10,
+ rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
+ round = Math.round,
+ labelArray = [], label,
+ maxValue = this.maximum || 0,
+ steps = this.steps, i = 0,
+ adjY,
+ pi = Math.PI,
cos = Math.cos,
sin = Math.sin,
- rendererAttributes, centerX, centerY, slice, slices, sprite, value,
- item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
- p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
-
- Ext.apply(seriesStyle, me.style || {});
-
- me.setBBox();
- bbox = me.bbox;
-
- //override theme colors
- if (me.colorSet) {
- colorArrayStyle = me.colorSet;
- colorArrayLength = colorArrayStyle.length;
- }
-
- //if not store or store is empty then there's nothing to draw
- if (!store || !store.getCount()) {
- return;
- }
-
- centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
- centerY = me.centerY = chartBBox.y + chartBBox.height;
- me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
- me.slices = slices = [];
- me.items = items = [];
-
- if (!me.value) {
- record = store.getAt(0);
- me.value = record.get(field);
- }
-
- value = me.value;
- if (me.needle) {
- sliceA = {
- series: me,
- value: value,
- startAngle: -180,
- endAngle: 0,
- rho: me.radius
- };
- splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
- slices.push(sliceA);
- } else {
- splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
- sliceA = {
- series: me,
- value: value,
- startAngle: -180,
- endAngle: splitAngle,
- rho: me.radius
- };
- sliceB = {
- series: me,
- value: me.maximum - value,
- startAngle: splitAngle,
- endAngle: 0,
- rho: me.radius
- };
- slices.push(sliceA, sliceB);
- }
-
- //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, colorArrayStyle && { fill: colorArrayStyle[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, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
- sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
- }
- slice.sprite = slice.sprite || [];
- item.sprite = sprite;
- slice.sprite.push(sprite);
- if (animate) {
- rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
- sprite._to = rendererAttributes;
- me.onAnimate(sprite, {
- to: rendererAttributes
+ labelConf = this.label,
+ renderer = labelConf.renderer || function(v) { return v; };
+
+ if (!this.labelArray) {
+ //draw scale
+ for (i = 0; i <= steps; i++) {
+ // TODO Adjust for height of text / 2 instead
+ adjY = (i === 0 || i === steps) ? 7 : 0;
+ label = surface.add({
+ type: 'text',
+ text: renderer(round(i / steps * maxValue)),
+ x: centerX + rho * cos(i / steps * pi - pi),
+ y: centerY + rho * sin(i / steps * pi - pi) - adjY,
+ 'text-anchor': 'middle',
+ 'stroke-width': 0.2,
+ zIndex: 10,
+ stroke: '#333'
});
- } else {
- rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
+ label.setAttributes({
hidden: false
- }), i, store);
- sprite.setAttributes(rendererAttributes, true);
+ }, true);
+ labelArray.push(label);
}
}
-
- if (me.needle) {
- splitAngle = splitAngle * Math.PI / 180;
-
- if (!me.needleSprite) {
- me.needleSprite = me.chart.surface.add({
- type: 'path',
- path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
- centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
- 'L', centerX + me.radius * cos(splitAngle),
- centerY + -Math.abs(me.radius * sin(splitAngle))],
- 'stroke-width': 4,
- 'stroke': '#222'
- });
- } else {
- if (animate) {
- me.onAnimate(me.needleSprite, {
- to: {
- path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
- centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
- 'L', centerX + me.radius * cos(splitAngle),
- centerY + -Math.abs(me.radius * sin(splitAngle))]
- }
- });
- } else {
- me.needleSprite.setAttributes({
- type: 'path',
- path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
- centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
- 'L', centerX + me.radius * cos(splitAngle),
- centerY + -Math.abs(me.radius * sin(splitAngle))]
- });
- }
+ else {
+ labelArray = this.labelArray;
+ //draw values
+ for (i = 0; i <= steps; i++) {
+ // TODO Adjust for height of text / 2 instead
+ adjY = (i === 0 || i === steps) ? 7 : 0;
+ labelArray[i].setAttributes({
+ text: renderer(round(i / steps * maxValue)),
+ x: centerX + rho * cos(i / steps * pi - pi),
+ y: centerY + rho * sin(i / steps * pi - pi) - adjY
+ }, true);
}
- me.needleSprite.setAttributes({
- hidden: false
- }, true);
}
-
- delete me.value;
- },
-
-<span id='Ext-chart.series.Gauge-method-setValue'> /**
-</span> * 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: function(storeItem, item, i, display) {},
-
- // @private callback for when placing a label sprite.
- onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
-
- // @private callback for when placing a callout.
- onPlaceCallout: function() {},
-
- // @private handles sprite animation for the series.
- onAnimate: function(sprite, attr) {
- sprite.show();
- return this.callParent(arguments);
- },
-
- isItemInPoint: function(x, y, item, i) {
- return false;
- },
-
- // @private shows all elements in the series.
- showAll: function() {
- if (!isNaN(this._index)) {
- this.__excludes[this._index] = false;
- this.drawSeries();
- }
- },
-
-<span id='Ext-chart.series.Gauge-method-getLegendColor'> /**
-</span> * Returns the color of the series (to be displayed as color for the series legend item).
- * @param item {Object} Info about the item; same format as returned by #getItemForPoint
- */
- getLegendColor: function(index) {
- var me = this;
- return me.colorArrayStyle[index % me.colorArrayStyle.length];
+ this.labelArray = labelArray;
}
-});
-
-</pre></pre></body></html>
\ No newline at end of file
+});</pre>
+</body>
+</html>