3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.chart.series.Radar
17 * @extends Ext.chart.series.Series
19 * Creates a Radar Chart. A Radar Chart is a useful visualization technique for comparing different quantitative values for
20 * a constrained number of categories.
22 * As with all other series, the Radar series must be appended in the *series* Chart array configuration. See the Chart
23 * documentation for more information. A typical configuration object for the radar series could be:
26 * var store = Ext.create('Ext.data.JsonStore', {
27 * fields: ['name', 'data1', 'data2', 'data3', 'data4', 'data5'],
29 * { 'name': 'metric one', 'data1': 10, 'data2': 12, 'data3': 14, 'data4': 8, 'data5': 13 },
30 * { 'name': 'metric two', 'data1': 7, 'data2': 8, 'data3': 16, 'data4': 10, 'data5': 3 },
31 * { 'name': 'metric three', 'data1': 5, 'data2': 2, 'data3': 14, 'data4': 12, 'data5': 7 },
32 * { 'name': 'metric four', 'data1': 2, 'data2': 14, 'data3': 6, 'data4': 1, 'data5': 23 },
33 * { 'name': 'metric five', 'data1': 27, 'data2': 38, 'data3': 36, 'data4': 13, 'data5': 33 }
37 * Ext.create('Ext.chart.Chart', {
38 * renderTo: Ext.getBody(),
96 * In this configuration we add three series to the chart. Each of these series is bound to the same
97 * categories field, `name` but bound to different properties for each category, `data1`, `data2` and
98 * `data3` respectively. All series display markers by having `showMarkers` enabled. The configuration
99 * for the markers of each series can be set by adding properties onto the markerConfig object.
100 * Finally we override some theme styling properties by adding properties to the `style` object.
104 Ext.define('Ext.chart.series.Radar', {
106 /* Begin Definitions */
108 extend: 'Ext.chart.series.Series',
110 requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
112 /* End Definitions */
115 alias: 'series.radar',
123 * @cfg {Object} style
124 * An object containing styles for overriding series styles from Theming.
128 constructor: function(config) {
129 this.callParent(arguments);
131 surface = me.chart.surface, i, l;
132 me.group = surface.getGroup(me.seriesId);
133 if (me.showMarkers) {
134 me.markerGroup = surface.getGroup(me.seriesId + '-markers');
139 * Draws the series for the current chart.
141 drawSeries: function() {
143 store = me.chart.getChartStore(),
147 animate = chart.animate,
148 field = me.field || me.yField,
149 surface = chart.surface,
150 chartBBox = chart.chartBBox,
161 l = store.getCount(),
162 startPath, path, x, y, rho,
164 seriesStyle = me.seriesStyle,
165 seriesLabelStyle = me.seriesLabelStyle,
166 first = chart.resizing || !me.radar,
167 axis = chart.axes && chart.axes.get(0),
168 aggregate = !(axis && axis.maximum);
172 maxValue = aggregate? 0 : (axis.maximum || 0);
174 Ext.apply(seriesStyle, me.style || {});
176 //if the store is empty then there's nothing to draw
177 if (!store || !store.getCount()) {
181 me.unHighlightItem();
182 me.cleanHighlights();
184 centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
185 centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
186 me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;
187 me.items = items = [];
190 //get all renderer fields
191 chart.series.each(function(series) {
192 fields.push(series.yField);
194 //get maxValue to interpolate
195 store.each(function(record, i) {
196 for (i = 0, nfields = fields.length; i < nfields; i++) {
197 maxValue = max(+record.get(fields[i]), maxValue);
201 //ensure non-zero value.
202 maxValue = maxValue || 1;
203 //create path and items
204 startPath = []; path = [];
205 store.each(function(record, i) {
206 rho = radius * record.get(field) / maxValue;
207 x = rho * cos(i / l * pi2);
208 y = rho * sin(i / l * pi2);
210 path.push('M', x + centerX, y + centerY);
211 startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);
213 path.push('L', x + centerX, y + centerY);
214 startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);
217 sprite: false, //TODO(nico): add markers
218 point: [centerX + x, centerY + y],
225 me.radar = surface.add(Ext.apply({
229 }, seriesStyle || {}));
232 if (chart.resizing) {
233 me.radar.setAttributes({
239 me.onAnimate(me.radar, {
242 }, seriesStyle || {})
245 me.radar.setAttributes(Ext.apply({
247 }, seriesStyle || {}), true);
249 //render markers, labels and callouts
250 if (me.showMarkers) {
257 // @private draws the markers for the lines (if any).
258 drawMarkers: function() {
261 surface = chart.surface,
262 markerStyle = Ext.apply({}, me.markerStyle || {}),
263 endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
265 type = endMarkerStyle.type,
266 markerGroup = me.markerGroup,
267 centerX = me.centerX,
268 centerY = me.centerY,
271 delete endMarkerStyle.type;
273 for (i = 0, l = items.length; i < l; i++) {
275 marker = markerGroup.getAt(i);
277 marker = Ext.chart.Shape[type](surface, Ext.apply({
290 if (chart.resizing) {
291 marker.setAttributes({
308 me.onAnimate(marker, {
313 marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);
318 isItemInPoint: function(x, y, item) {
323 return (abs(point[0] - x) <= tolerance &&
324 abs(point[1] - y) <= tolerance);
327 // @private callback for when creating a label sprite.
328 onCreateLabel: function(storeItem, item, i, display) {
330 group = me.labelsGroup,
332 centerX = me.centerX,
333 centerY = me.centerY,
335 endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
337 return me.chart.surface.add(Ext.apply({
339 'text-anchor': 'middle',
346 // @private callback for when placing a label sprite.
347 onPlaceLabel: function(label, storeItem, item, i, display, animate) {
350 resizing = chart.resizing,
352 format = config.renderer,
353 field = config.field,
354 centerX = me.centerX,
355 centerY = me.centerY,
363 label.setAttributes({
364 text: format(storeItem.get(field)),
370 label.setAttributes({
378 me.onAnimate(label, {
382 label.setAttributes(opt, true);
387 // @private for toggling (show/hide) series.
388 toggleAll: function(show) {
390 i, ln, shadow, shadows;
392 Ext.chart.series.Radar.superclass.hideAll.call(me);
395 Ext.chart.series.Radar.superclass.showAll.call(me);
398 me.radar.setAttributes({
402 if (me.radar.shadows) {
403 for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {
405 shadow.setAttributes({
413 // @private hide all elements in the series.
414 hideAll: function() {
415 this.toggleAll(false);
419 // @private show all elements in the series.
420 showAll: function() {
421 this.toggleAll(true);
424 // @private hide all markers that belong to `markerGroup`
425 hideMarkers: function(index) {
427 count = me.markerGroup && me.markerGroup.getCount() || 0,
429 for (; i < count; i++) {
430 me.markerGroup.getAt(i).hide(true);