]> git.proxmox.com Git - extjs.git/blame - extjs/packages/charts/src/chart/PolarChart.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / charts / src / chart / PolarChart.js
CommitLineData
6527f429
DM
1/**\r
2 * @class Ext.chart.PolarChart\r
3 * @extends Ext.chart.AbstractChart\r
4 * @xtype polar\r
5 *\r
6 * Represent a chart that uses polar coordinates.\r
7 * A polar chart has two axes: an angular axis (which is a circle) and\r
8 * a radial axis (a straight line from the center to the edge of the circle).\r
9 * The angular axis is usually a Category axis while the radial axis is\r
10 * typically numerical. \r
11 *\r
12 * Pie charts and Radar charts are common examples of Polar charts.\r
13 *\r
14 */\r
15Ext.define('Ext.chart.PolarChart', {\r
16 extend: 'Ext.chart.AbstractChart',\r
17 requires: [\r
18 'Ext.chart.grid.CircularGrid',\r
19 'Ext.chart.grid.RadialGrid'\r
20 ],\r
21 xtype: 'polar',\r
22 isPolar: true,\r
23\r
24 config: {\r
25 /**\r
26 * @cfg {Array} center Determines the center of the polar chart.\r
27 * Updated when the chart performs layout.\r
28 */\r
29 center: [0, 0],\r
30 /**\r
31 * @cfg {Number} radius Determines the radius of the polar chart.\r
32 * Updated when the chart performs layout.\r
33 */\r
34 radius: 0,\r
35\r
36 /**\r
37 * @cfg {Number} innerPadding The amount of inner padding in pixels.\r
38 * Inner padding is the padding from the outermost angular axis to the series.\r
39 */\r
40 innerPadding: 0\r
41 },\r
42\r
43 getDirectionForAxis: function (position) {\r
44 return position === 'radial' ? 'Y' : 'X';\r
45 },\r
46\r
47 applyCenter: function (center, oldCenter) {\r
48 if (oldCenter && center[0] === oldCenter[0] && center[1] === oldCenter[1]) {\r
49 return;\r
50 }\r
51 return [+center[0], +center[1]];\r
52 },\r
53\r
54 updateCenter: function (center) {\r
55 var me = this,\r
56 axes = me.getAxes(),\r
57 series = me.getSeries(),\r
58 i, ln, axis, seriesItem;\r
59 \r
60 for (i = 0, ln = axes.length; i < ln; i++) {\r
61 axis = axes[i];\r
62 axis.setCenter(center);\r
63 }\r
64\r
65 for (i = 0, ln = series.length; i < ln; i++) {\r
66 seriesItem = series[i];\r
67 seriesItem.setCenter(center);\r
68 }\r
69 },\r
70\r
71 applyInnerPadding: function (padding, oldPadding) {\r
72 return Ext.isNumber(padding) ? padding : oldPadding;\r
73 },\r
74\r
75 doSetSurfaceRect: function (surface, rect) {\r
76 var mainRect = this.getMainRect();\r
77 surface.setRect(rect);\r
78 surface.matrix.set(1, 0, 0, 1, mainRect[0] - rect[0], mainRect[1] - rect[1]);\r
79 surface.inverseMatrix.set(1, 0, 0, 1, rect[0] - mainRect[0], rect[1] - mainRect[1]);\r
80 },\r
81\r
82 applyAxes: function (newAxes, oldAxes) {\r
83 var me = this,\r
84 firstSeries = Ext.Array.from(me.config.series)[0],\r
85 i, ln, axis, foundAngular;\r
86\r
87 if (firstSeries.type === 'radar' && newAxes && newAxes.length) {\r
88 // For compatibility with ExtJS: add a default angular axis if it's missing\r
89 for (i = 0, ln = newAxes.length; i < ln; i++) {\r
90 axis = newAxes[i];\r
91 if (axis.position === 'angular') {\r
92 foundAngular = true;\r
93 break;\r
94 }\r
95 }\r
96 if (!foundAngular) {\r
97 newAxes.push({\r
98 type: 'category',\r
99 position: 'angular',\r
100 fields: firstSeries.xField || firstSeries.angleField,\r
101 style: {\r
102 estStepSize: 1\r
103 },\r
104 grid: true\r
105 });\r
106 }\r
107 }\r
108 return this.callParent(arguments);\r
109 },\r
110\r
111 performLayout: function () {\r
112 var me = this,\r
113 applyThickness = true;\r
114\r
115 try {\r
116 me.animationSuspendCount++;\r
117 if (this.callParent() === false) {\r
118 applyThickness = false;\r
119 // Animation will be decremented in finally block\r
120 return;\r
121 }\r
122 me.suspendThicknessChanged();\r
123\r
124 var chartRect = me.getSurface('chart').getRect(),\r
125 inset = me.getInsetPadding(),\r
126 inner = me.getInnerPadding(),\r
127 shrinkBox = Ext.apply({}, inset), side,\r
128 width = chartRect[2] - inset.left - inset.right,\r
129 height = chartRect[3] - inset.top - inset.bottom,\r
130 mainRect = [inset.left, inset.top, width, height],\r
131 seriesList = me.getSeries(), series,\r
132 innerWidth = width - inner * 2,\r
133 innerHeight = height - inner * 2,\r
134 center = [innerWidth * 0.5 + inner, innerHeight * 0.5 + inner],\r
135 radius = Math.min(innerWidth, innerHeight) * 0.5,\r
136 axes = me.getAxes(), axis, thickness, halfLineWidth,\r
137 angularAxes = [], radialAxes = [],\r
138 seriesRadius = radius - inner,\r
139 i, ln, shrinkRadius, floating, floatingValue,\r
140 gaugeSeries, gaugeRadius;\r
141\r
142 me.setMainRect(mainRect);\r
143\r
144 me.doSetSurfaceRect(me.getSurface(), mainRect);\r
145 for (i = 0, ln = me.surfaceMap.grid && me.surfaceMap.grid.length; i < ln; i++) {\r
146 me.doSetSurfaceRect(me.surfaceMap.grid[i], chartRect);\r
147 }\r
148\r
149 for (i = 0, ln = axes.length; i < ln; i++) {\r
150 axis = axes[i];\r
151 switch (axis.getPosition()) {\r
152 case 'angular':\r
153 angularAxes.push(axis);\r
154 break;\r
155 case 'radial':\r
156 radialAxes.push(axis);\r
157 break;\r
158 }\r
159 }\r
160\r
161 for (i = 0, ln = angularAxes.length; i < ln; i++) {\r
162 axis = angularAxes[i];\r
163 floating = axis.getFloating();\r
164 floatingValue = floating ? floating.value : null;\r
165 me.doSetSurfaceRect(axis.getSurface(), chartRect);\r
166 thickness = axis.getThickness();\r
167 for (side in shrinkBox) {\r
168 shrinkBox[side] += thickness;\r
169 }\r
170 width = chartRect[2] - shrinkBox.left - shrinkBox.right;\r
171 height = chartRect[3] - shrinkBox.top - shrinkBox.bottom;\r
172 shrinkRadius = Math.min(width, height) * 0.5;\r
173 if (i === 0) {\r
174 seriesRadius = shrinkRadius - inner;\r
175 }\r
176 axis.setMinimum(0);\r
177 axis.setLength(shrinkRadius);\r
178 axis.getSprites();\r
179 halfLineWidth = axis.sprites[0].attr.lineWidth * 0.5;\r
180 for (side in shrinkBox) {\r
181 shrinkBox[side] += halfLineWidth;\r
182 }\r
183 }\r
184\r
185 for (i = 0, ln = radialAxes.length; i < ln; i++) {\r
186 axis = radialAxes[i];\r
187 me.doSetSurfaceRect(axis.getSurface(), chartRect);\r
188 axis.setMinimum(0);\r
189 axis.setLength(seriesRadius);\r
190 axis.getSprites();\r
191 }\r
192\r
193 for (i = 0, ln = seriesList.length; i < ln; i++) {\r
194 series = seriesList[i];\r
195 if (series.type === 'gauge' && !gaugeSeries) {\r
196 gaugeSeries = series;\r
197 } else {\r
198 series.setRadius(seriesRadius);\r
199 }\r
200 me.doSetSurfaceRect(series.getSurface(), mainRect);\r
201 }\r
202\r
203 me.doSetSurfaceRect(me.getSurface('overlay'), chartRect);\r
204 if (gaugeSeries) {\r
205 gaugeSeries.setRect(mainRect);\r
206 gaugeRadius = gaugeSeries.getRadius() - inner;\r
207 me.setRadius(gaugeRadius);\r
208 me.setCenter(gaugeSeries.getCenter());\r
209 gaugeSeries.setRadius(gaugeRadius);\r
210 if (axes.length && axes[0].getPosition() === 'gauge') {\r
211 axis = axes[0];\r
212 me.doSetSurfaceRect(axis.getSurface(), chartRect);\r
213 axis.setTotalAngle(gaugeSeries.getTotalAngle());\r
214 axis.setLength(gaugeRadius);\r
215 }\r
216 } else {\r
217 me.setRadius(radius);\r
218 me.setCenter(center);\r
219 }\r
220 me.redraw();\r
221 } catch (e) { // catch is required in IE8 (try/finally not supported)\r
222 //<debug>\r
223 Ext.log.error(me.$className + ': Unhandled Exception: ', e.description || e.message);\r
224 //</debug>\r
225 throw e;\r
226 }\r
227 finally {\r
228 me.animationSuspendCount--;\r
229 if (applyThickness) {\r
230 me.resumeThicknessChanged();\r
231 }\r
232 }\r
233 },\r
234\r
235 refloatAxes: function () {\r
236 var me = this,\r
237 axes = me.getAxes(),\r
238 mainRect = me.getMainRect(),\r
239 floating, value, alongAxis,\r
240 i, n, axis, radius;\r
241\r
242 if (!mainRect) {\r
243 return;\r
244 }\r
245\r
246 radius = 0.5 * Math.min(mainRect[2], mainRect[3]);\r
247\r
248 for (i = 0, n = axes.length; i < n; i++) {\r
249 axis = axes[i];\r
250 floating = axis.getFloating();\r
251 value = floating ? floating.value : null;\r
252 if (value !== null) {\r
253 alongAxis = me.getAxis(floating.alongAxis);\r
254 if (axis.getPosition() === 'angular') {\r
255 if (alongAxis) {\r
256 value = alongAxis.getLength() * value / alongAxis.getRange()[1];\r
257 } else {\r
258 value = 0.01 * value * radius;\r
259 }\r
260 axis.sprites[0].setAttributes({length: value}, true);\r
261 } else {\r
262 if (alongAxis) {\r
263 if (Ext.isString(value)) {\r
264 value = alongAxis.getCoordFor(value);\r
265 }\r
266 value = value / (alongAxis.getRange()[1] + 1) * Math.PI * 2 - Math.PI * 1.5 +\r
267 axis.getRotation();\r
268 } else {\r
269 value = Ext.draw.Draw.rad(value);\r
270 }\r
271 axis.sprites[0].setAttributes({baseRotation: value}, true);\r
272 }\r
273 }\r
274 }\r
275 },\r
276\r
277 redraw: function () {\r
278 var me = this,\r
279 axes = me.getAxes(), axis,\r
280 seriesList = me.getSeries(), series,\r
281 i, ln;\r
282\r
283 for (i = 0, ln = axes.length; i < ln; i++) {\r
284 axis = axes[i];\r
285 axis.getSprites();\r
286 }\r
287\r
288 for (i = 0, ln = seriesList.length; i < ln; i++) {\r
289 series = seriesList[i];\r
290 series.getSprites();\r
291 }\r
292\r
293 me.renderFrame();\r
294 me.callParent(arguments);\r
295 },\r
296\r
297 renderFrame: function () {\r
298 this.refloatAxes();\r
299 this.callParent();\r
300 }\r
301});\r