| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />  <script type="text/javascript" src="../resources/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-series-Gauge'>/**</span> * @class Ext.chart.series.Gauge *  * 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 instantiating the * visualization and using the `setValue` method to adjust the value you want. * * An example of Gauge visualization: * *     @example *     var store = Ext.create('Ext.data.JsonStore', { *         fields: ['data'], *         data: [ *             { 'value':80 } *         ] *     }); * *     Ext.create('Ext.chart.Chart', { *         renderTo: Ext.getBody(), *         store: store, *         width: 400, *         height: 250, *         animate: true, *         insetPadding: 30, *         axes: [{ *             type: 'gauge', *             position: 'gauge', *             minimum: 0, *             maximum: 100, *             steps: 10, *             margin: 10 *         }], *         series: [{ *             type: 'gauge', *             field: 'value', *             donut: 30, *             colorSet: ['#F49D10', '#ddd'] *         }] *     }); * *     Ext.widget("button", { *         renderTo: Ext.getBody(), *         text: "Refresh", *         handler: function() { *             store.getAt(0).set('value', Math.round(Math.random()*100)); *         } *     }); *  * In this example 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 */Ext.define('Ext.chart.series.Gauge', {    /* Begin Definitions */    extend: 'Ext.chart.series.Series',    /* 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.     */    highlightDuration: 150,<span id='Ext-chart-series-Gauge-cfg-angleField'>    /**</span>     * @cfg {String} angleField (required)     * The store record field name to be used for the pie angles.     * The values bound to this field name must be positive real numbers.     */    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.     */    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.     */    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,            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                }            },            {                "stroke-width": 2,                "stroke-opacity": 1,                stroke: 'rgb(100, 100, 100)',                translate: {                    x: 0.6,                    y: 1                }            }]        });        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.getChartStore(),            data = store.data.items,            i, ln, rec;        //Add yFields to be used in Legend.js        me.yField = [];        if (me.label.field) {            for (i = 0, ln = data.length; i < ln; i++) {                rec = data[i];                me.yField.push(rec.get(me.label.field));            }        }    },    // @private returns an object with properties for a Slice    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,            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"]]            };        }    },    // @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-series-Gauge-method-drawSeries'>    /**</span>     * Draws the series for the current chart.     */    drawSeries: function() {        var me = this,            chart = me.chart,            store = chart.getChartStore(),            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,            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],            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() || me.seriesIsHidden) {            me.hide();            me.items = [];            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                });            } else {                rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {                    hidden: false                }), i, store);                sprite.setAttributes(rendererAttributes, true);            }        }                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))]                    });                }            }            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) {        var me = this,            cx = me.centerX,            cy = me.centerY,            abs = Math.abs,            dx = abs(x - cx),            dy = abs(y - cy),            startAngle = item.startAngle,            endAngle = item.endAngle,            rho = Math.sqrt(dx * dx + dy * dy),            angle = Math.atan2(y - cy, x - cx) / me.rad;        //Only trigger events for the filled portion of the Gauge.        return (i === 0) && (angle >= startAngle && angle < endAngle &&                              rho >= item.startRho && rho <= item.endRho);    },        // @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];    }});</pre></body></html>
 |