| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 | <!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-Radar'>/**</span> * @class Ext.chart.series.Radar * * Creates a Radar Chart. A Radar Chart is a useful visualization technique for comparing different quantitative values for * a constrained number of categories. * * As with all other series, the Radar series must be appended in the *series* Chart array configuration. See the Chart * documentation for more information. A typical configuration object for the radar series could be: * *     @example *     var store = Ext.create('Ext.data.JsonStore', { *         fields: ['name', 'data1', 'data2', 'data3'], *         data: [ *             { 'name': 'metric one',   'data1': 14, 'data2': 12, 'data3': 13 }, *             { 'name': 'metric two',   'data1': 16, 'data2':  8, 'data3':  3 }, *             { 'name': 'metric three', 'data1': 14, 'data2':  2, 'data3':  7 }, *             { 'name': 'metric four',  'data1':  6, 'data2': 14, 'data3': 23 }, *             { 'name': 'metric five',  'data1': 36, 'data2': 38, 'data3': 33 } *         ] *     }); * *     Ext.create('Ext.chart.Chart', { *         renderTo: Ext.getBody(), *         width: 500, *         height: 300, *         animate: true, *         theme:'Category2', *         store: store, *         axes: [{ *             type: 'Radial', *             position: 'radial', *             label: { *                 display: true *             } *         }], *         series: [{ *             type: 'radar', *             xField: 'name', *             yField: 'data1', *             showInLegend: true, *             showMarkers: true, *             markerConfig: { *                 radius: 5, *                 size: 5 *             }, *             style: { *                 'stroke-width': 2, *                 fill: 'none' *             } *         },{ *             type: 'radar', *             xField: 'name', *             yField: 'data2', *             showMarkers: true, *             showInLegend: true, *             markerConfig: { *                 radius: 5, *                 size: 5 *             }, *             style: { *                 'stroke-width': 2, *                 fill: 'none' *             } *         },{ *             type: 'radar', *             xField: 'name', *             yField: 'data3', *             showMarkers: true, *             showInLegend: true, *             markerConfig: { *                 radius: 5, *                 size: 5 *             }, *             style: { *                 'stroke-width': 2, *                 fill: 'none' *             } *         }] *     }); * * In this configuration we add three series to the chart. Each of these series is bound to the same * categories field, `name` but bound to different properties for each category, `data1`, `data2` and * `data3` respectively. All series display markers by having `showMarkers` enabled. The configuration * for the markers of each series can be set by adding properties onto the markerConfig object. * Finally we override some theme styling properties by adding properties to the `style` object. * * @xtype radar */Ext.define('Ext.chart.series.Radar', {    /* Begin Definitions */    extend: 'Ext.chart.series.Series',    requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],    /* End Definitions */    type: "radar",    alias: 'series.radar',    rad: Math.PI / 180,    showInLegend: false,<span id='Ext-chart-series-Radar-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,            surface = me.chart.surface, i, l;        me.group = surface.getGroup(me.seriesId);        if (me.showMarkers) {            me.markerGroup = surface.getGroup(me.seriesId + '-markers');        }    },<span id='Ext-chart-series-Radar-method-drawSeries'>    /**</span>     * Draws the series for the current chart.     */    drawSeries: function() {        var me = this,            store = me.chart.getChartStore(),            data = store.data.items,            d, record,            group = me.group,            sprite,            chart = me.chart,            seriesItems = chart.series.items,            s, sLen, series,            animate = chart.animate,            field = me.field || me.yField,            surface = chart.surface,            chartBBox = chart.chartBBox,            seriesIdx = me.seriesIdx,            colorArrayStyle = me.colorArrayStyle,            centerX, centerY,            items,            radius,            maxValue = 0,            fields = [],            max = Math.max,            cos = Math.cos,            sin = Math.sin,            pi2 = Math.PI * 2,            l = store.getCount(),            startPath, path, x, y, rho,            i, nfields,            seriesStyle = me.seriesStyle,            seriesLabelStyle = me.seriesLabelStyle,            first = chart.resizing || !me.radar,            axis = chart.axes && chart.axes.get(0),            aggregate = !(axis && axis.maximum);        me.setBBox();                maxValue = aggregate? 0 : (axis.maximum || 0);                Ext.apply(seriesStyle, me.style || {});        //if the store is empty then there's nothing to draw        if (!store || !store.getCount() || me.seriesIsHidden) {            me.hide();            me.items = [];            if (me.radar) {                me.radar.hide(true);            }            me.radar = null;            return;        }                if(!seriesStyle['stroke']){            seriesStyle['stroke'] = colorArrayStyle[seriesIdx % colorArrayStyle.length];        }        me.unHighlightItem();        me.cleanHighlights();        centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);        centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);        me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;        me.items = items = [];        if (aggregate) {            //get all renderer fields            for (s = 0, sLen = seriesItems.length; s < sLen; s++) {                series = seriesItems[s];                fields.push(series.yField);            }            //get maxValue to interpolate            for (d = 0; d < l; d++) {                record = data[d];                for (i = 0, nfields = fields.length; i < nfields; i++) {                    maxValue = max(+record.get(fields[i]), maxValue);                }            }        }        //ensure non-zero value.        maxValue = maxValue || 1;        //create path and items        startPath = []; path = [];        for (i = 0; i < l; i++) {            record = data[i];            rho = radius * record.get(field) / maxValue;            x = rho * cos(i / l * pi2);            y = rho * sin(i / l * pi2);            if (i == 0) {                path.push('M', x + centerX, y + centerY);                startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);            } else {                path.push('L', x + centerX, y + centerY);                startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);            }            items.push({                sprite: false, //TODO(nico): add markers                point: [centerX + x, centerY + y],                storeItem: record,                series: me            });        }        path.push('Z');        //create path sprite        if (!me.radar) {            me.radar = surface.add(Ext.apply({                type: 'path',                group: group,                path: startPath            }, seriesStyle || {}));        }        //reset on resizing        if (chart.resizing) {            me.radar.setAttributes({                path: startPath            }, true);        }        //render/animate        if (chart.animate) {            me.onAnimate(me.radar, {                to: Ext.apply({                    path: path                }, seriesStyle || {})            });        } else {            me.radar.setAttributes(Ext.apply({                path: path            }, seriesStyle || {}), true);        }        //render markers, labels and callouts        if (me.showMarkers) {            me.drawMarkers();        }        me.renderLabels();        me.renderCallouts();    },    // @private draws the markers for the lines (if any).    drawMarkers: function() {        var me = this,            chart = me.chart,            surface = chart.surface,            markerStyle = Ext.apply({}, me.markerStyle || {}),            endMarkerStyle = Ext.apply(markerStyle, me.markerConfig, {                fill: me.colorArrayStyle[me.seriesIdx % me.colorArrayStyle.length]            }),            items = me.items,            type = endMarkerStyle.type,            markerGroup = me.markerGroup,            centerX = me.centerX,            centerY = me.centerY,            item, i, l, marker;        delete endMarkerStyle.type;        for (i = 0, l = items.length; i < l; i++) {            item = items[i];            marker = markerGroup.getAt(i);            if (!marker) {                marker = Ext.chart.Shape[type](surface, Ext.apply({                    group: markerGroup,                    x: 0,                    y: 0,                    translate: {                        x: centerX,                        y: centerY                    }                }, endMarkerStyle));            }            else {                marker.show();            }            item.sprite = marker;            if (chart.resizing) {                marker.setAttributes({                    x: 0,                    y: 0,                    translate: {                        x: centerX,                        y: centerY                    }                }, true);            }            marker._to = {                translate: {                    x: item.point[0],                    y: item.point[1]                }            };            //render/animate            if (chart.animate) {                me.onAnimate(marker, {                    to: marker._to                });            }            else {                marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);            }        }    },    isItemInPoint: function(x, y, item) {        var point,            tolerance = 10,            abs = Math.abs;        point = item.point;        return (abs(point[0] - x) <= tolerance &&                abs(point[1] - y) <= tolerance);    },    // @private callback for when creating a label sprite.    onCreateLabel: function(storeItem, item, i, display) {        var me = this,            group = me.labelsGroup,            config = me.label,            centerX = me.centerX,            centerY = me.centerY,            point = item.point,            endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);        return me.chart.surface.add(Ext.apply({            'type': 'text',            'text-anchor': 'middle',            'group': group,            'x': centerX,            'y': centerY        }, config || {}));    },    // @private callback for when placing a label sprite.    onPlaceLabel: function(label, storeItem, item, i, display, animate) {        var me = this,            chart = me.chart,            resizing = chart.resizing,            config = me.label,            format = config.renderer,            field = config.field,            centerX = me.centerX,            centerY = me.centerY,            opt = {                x: item.point[0],                y: item.point[1]            },            x = opt.x - centerX,            y = opt.y - centerY;        label.setAttributes({            text: format(storeItem.get(field)),            hidden: true        },        true);        if (resizing) {            label.setAttributes({                x: centerX,                y: centerY            }, true);        }        if (animate) {            label.show(true);            me.onAnimate(label, {                to: opt            });        } else {            label.setAttributes(opt, true);            label.show(true);        }    },    // @private for toggling (show/hide) series.    toggleAll: function(show) {        var me = this,            i, ln, shadow, shadows;        if (!show) {            Ext.chart.series.Radar.superclass.hideAll.call(me);        }        else {            Ext.chart.series.Radar.superclass.showAll.call(me);        }        if (me.radar) {            me.radar.setAttributes({                hidden: !show            }, true);            //hide shadows too            if (me.radar.shadows) {                for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {                    shadow = shadows[i];                    shadow.setAttributes({                        hidden: !show                    }, true);                }            }        }    },    // @private hide all elements in the series.    hideAll: function() {        this.toggleAll(false);        this.hideMarkers(0);    },    // @private show all elements in the series.    showAll: function() {        this.toggleAll(true);    },    // @private hide all markers that belong to `markerGroup`    hideMarkers: function(index) {        var me = this,            count = me.markerGroup && me.markerGroup.getCount() || 0,            i = index || 0;        for (; i < count; i++) {            me.markerGroup.getAt(i).hide(true);        }    }});</pre></body></html>
 |