X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/docs/source/Gauge.html diff --git a/docs/source/Gauge.html b/docs/source/Gauge.html index e3b6fcb9..63fb7a41 100644 --- a/docs/source/Gauge.html +++ b/docs/source/Gauge.html @@ -3,8 +3,8 @@
/** - * @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. +/** + * @class Ext.chart.axis.Gauge + * @extends Ext.chart.axis.Abstract * - * 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 + * 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: + * + * 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, - - /** - * @cfg {Number} highlightDuration - * The duration for the pie slice highlight effect. + /** + * @cfg {Number} minimum (required) + * The minimum value of the interval to be displayed in the axis. */ - highlightDuration: 150, - /** - * @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. + /** + * @cfg {Number} maximum (required) + * The maximum value of the interval to be displayed in the axis. */ - angleField: false, - /** - * @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. + /** + * @cfg {Number} steps (required) + * The number of steps and tick marks to add to the interval. */ - donut: false, - /** - * @cfg {Boolean} showInLegend - * Whether to add the pie chart elements as legend items. Default's false. + /** + * @cfg {Number} [margin=10] + * The offset positioning of the tick marks and labels in pixels. */ - showInLegend: false, - /** - * @cfg {Object} style - * An object containing styles for overriding series styles from Theming. + /** + * @cfg {String} title + * The title for the Axis. */ - 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 - }; + /** + * Updates the {@link #title} of this axis. + * @param {String} title + */ + setTitle: function(title) { + this.title = title; + this.drawTitle(); }, - /** - * 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; - }, - - /** - * 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(); - } - }, - - /** - * 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; } -}); - -+});