1 | define(["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/connect", "dojo/_base/array", |
---|
2 | "dojo/dom-geometry", "dojo/_base/fx", "dojo/fx", "dojo/sniff", |
---|
3 | "./Base", "./_PlotEvents", "./common", "../axis2d/common", |
---|
4 | "dojox/gfx", "dojox/gfx/matrix", "dojox/gfx/fx", "dojox/lang/functional", |
---|
5 | "dojox/lang/utils", "dojo/fx/easing"], |
---|
6 | function(lang, declare, hub, arr, domGeom, baseFx, coreFx, has, |
---|
7 | Base, PlotEvents, dc, da, g, m, gfxfx, df, du, easing){ |
---|
8 | |
---|
9 | var FUDGE_FACTOR = 0.2; // use to overlap fans |
---|
10 | |
---|
11 | var Spider = declare("dojox.charting.plot2d.Spider", [Base, PlotEvents], { |
---|
12 | // summary: |
---|
13 | // The plot that represents a typical Spider chart. |
---|
14 | defaultParams: { |
---|
15 | labels: true, |
---|
16 | ticks: false, |
---|
17 | fixed: true, |
---|
18 | precision: 1, |
---|
19 | labelOffset: -10, |
---|
20 | labelStyle: "default", // default/rows/auto |
---|
21 | htmlLabels: true, // use HTML to draw labels |
---|
22 | startAngle: -90, // start angle for slices in degrees |
---|
23 | divisions: 3, // radius tick count |
---|
24 | axisColor: "", // spider axis color |
---|
25 | axisWidth: 0, // spider axis stroke width |
---|
26 | spiderColor: "", // spider web color |
---|
27 | spiderWidth: 0, // spider web stroke width |
---|
28 | seriesWidth: 0, // plot border with |
---|
29 | seriesFillAlpha: 0.2, // plot fill alpha |
---|
30 | spiderOrigin: 0.16, |
---|
31 | markerSize: 3, // radius of plot vertex (px) |
---|
32 | spiderType: "polygon", //"circle" |
---|
33 | animationType: easing.backOut, |
---|
34 | axisTickFont: "", |
---|
35 | axisTickFontColor: "", |
---|
36 | axisFont: "", |
---|
37 | axisFontColor: "" |
---|
38 | }, |
---|
39 | optionalParams: { |
---|
40 | radius: 0, |
---|
41 | font: "", |
---|
42 | fontColor: "" |
---|
43 | }, |
---|
44 | |
---|
45 | constructor: function(chart, kwArgs){ |
---|
46 | // summary: |
---|
47 | // Create a Spider plot. |
---|
48 | // chart: dojox/charting/Chart |
---|
49 | // The chart this plot belongs to. |
---|
50 | // kwArgs: dojox.charting.plot2d.__DefaultCtorArgs? |
---|
51 | // An optional keyword arguments object to help define this plot's parameters. |
---|
52 | this.opt = lang.clone(this.defaultParams); |
---|
53 | du.updateWithObject(this.opt, kwArgs); |
---|
54 | du.updateWithPattern(this.opt, kwArgs, this.optionalParams); |
---|
55 | this.dyn = []; |
---|
56 | this.datas = {}; |
---|
57 | this.labelKey = []; |
---|
58 | this.oldSeriePoints = {}; |
---|
59 | this.animations = {}; |
---|
60 | }, |
---|
61 | clear: function(){ |
---|
62 | // summary: |
---|
63 | // Clear out all of the information tied to this plot. |
---|
64 | // returns: dojox/charting/plot2d/Spider |
---|
65 | // A reference to this plot for functional chaining. |
---|
66 | this.inherited(arguments); |
---|
67 | this.dyn = []; |
---|
68 | this.axes = []; |
---|
69 | this.datas = {}; |
---|
70 | this.labelKey = []; |
---|
71 | this.oldSeriePoints = {}; |
---|
72 | this.animations = {}; |
---|
73 | return this; // dojox/charting/plot2d/Spider |
---|
74 | }, |
---|
75 | setAxis: function(axis){ |
---|
76 | // summary: |
---|
77 | // Optionally set axis min and max property. |
---|
78 | // returns: dojox/charting/plot2d/Spider |
---|
79 | // The reference to this plot for functional chaining. |
---|
80 | |
---|
81 | // override the computed min/max with provided values if any |
---|
82 | if(axis){ |
---|
83 | if(axis.opt.min != undefined){ |
---|
84 | this.datas[axis.name].min = axis.opt.min; |
---|
85 | } |
---|
86 | if(axis.opt.max != undefined){ |
---|
87 | this.datas[axis.name].max = axis.opt.max; |
---|
88 | } |
---|
89 | } |
---|
90 | return this; // dojox/charting/plot2d/Spider |
---|
91 | }, |
---|
92 | addSeries: function(run){ |
---|
93 | // summary: |
---|
94 | // Add a data series to this plot. |
---|
95 | // run: dojox.charting.Series |
---|
96 | // The series to be added. |
---|
97 | // returns: dojox/charting/plot2d/Base |
---|
98 | // A reference to this plot for functional chaining. |
---|
99 | this.series.push(run); |
---|
100 | var key; |
---|
101 | for(key in run.data){ |
---|
102 | var val = run.data[key], |
---|
103 | data = this.datas[key]; |
---|
104 | if(data){ |
---|
105 | data.vlist.push(val); |
---|
106 | data.min = Math.min(data.min, val); |
---|
107 | data.max = Math.max(data.max, val); |
---|
108 | }else{ |
---|
109 | var axisKey = "__"+key; |
---|
110 | this.axes.push(axisKey); |
---|
111 | this[axisKey] = key; |
---|
112 | this.datas[key] = {min: val, max: val, vlist: [val]}; |
---|
113 | } |
---|
114 | } |
---|
115 | if(this.labelKey.length <= 0){ |
---|
116 | for(key in run.data){ |
---|
117 | this.labelKey.push(key); |
---|
118 | } |
---|
119 | } |
---|
120 | return this; // dojox.charting.plot2d.Base |
---|
121 | }, |
---|
122 | getSeriesStats: function(){ |
---|
123 | // summary: |
---|
124 | // Calculate the min/max on all attached series in both directions. |
---|
125 | // returns: Object |
---|
126 | // {hmin, hmax, vmin, vmax} min/max in both directions. |
---|
127 | return dc.collectSimpleStats(this.series); // Object |
---|
128 | }, |
---|
129 | render: function(dim, offsets){ |
---|
130 | // summary: |
---|
131 | // Render the plot on the chart. |
---|
132 | // dim: Object |
---|
133 | // An object of the form { width, height }. |
---|
134 | // offsets: Object |
---|
135 | // An object of the form { l, r, t, b }. |
---|
136 | // returns: dojox/charting/plot2d/Spider |
---|
137 | // A reference to this plot for functional chaining. |
---|
138 | if(!this.dirty){ return this; } |
---|
139 | this.dirty = false; |
---|
140 | this.cleanGroup(); |
---|
141 | var s = this.group, t = this.chart.theme; |
---|
142 | this.resetEvents(); |
---|
143 | |
---|
144 | if(!this.series || !this.series.length){ |
---|
145 | return this; |
---|
146 | } |
---|
147 | |
---|
148 | // calculate the geometry |
---|
149 | var o = this.opt, ta = t.axis, |
---|
150 | rx = (dim.width - offsets.l - offsets.r) / 2, |
---|
151 | ry = (dim.height - offsets.t - offsets.b) / 2, |
---|
152 | r = Math.min(rx, ry), |
---|
153 | axisTickFont = o.font || (ta.majorTick && ta.majorTick.font) || (ta.tick && ta.tick.font) || "normal normal normal 7pt Tahoma", |
---|
154 | axisFont = o.axisFont || (ta.tick && ta.tick.titleFont) || "normal normal normal 11pt Tahoma", |
---|
155 | axisTickFontColor = o.axisTickFontColor || (ta.majorTick && ta.majorTick.fontColor) || (ta.tick && ta.tick.fontColor) || "silver", |
---|
156 | axisFontColor = o.axisFontColor || (ta.tick && ta.tick.titleFontColor) || "black", |
---|
157 | axisColor = o.axisColor || (ta.tick && ta.tick.axisColor) || "silver", |
---|
158 | spiderColor = o.spiderColor || (ta.tick && ta.tick.spiderColor) || "silver", |
---|
159 | axisWidth = o.axisWidth || (ta.stroke && ta.stroke.width) || 2, |
---|
160 | spiderWidth = o.spiderWidth || (ta.stroke && ta.stroke.width) || 2, |
---|
161 | seriesWidth = o.seriesWidth || (ta.stroke && ta.stroke.width) || 2, |
---|
162 | asize = g.normalizedLength(g.splitFontString(axisFont).size), |
---|
163 | startAngle = m._degToRad(o.startAngle), |
---|
164 | start = startAngle, labels, shift, labelR, |
---|
165 | outerPoints, innerPoints, divisionPoints, divisionRadius, labelPoints, |
---|
166 | ro = o.spiderOrigin, dv = o.divisions >= 3 ? o.divisions : 3, ms = o.markerSize, |
---|
167 | spt = o.spiderType, at = o.animationType, lboffset = o.labelOffset < -10 ? o.labelOffset : -10, |
---|
168 | axisExtra = 0.2, |
---|
169 | i, j, point, len, fontWidth, render, serieEntry, run, data, min, max, distance; |
---|
170 | |
---|
171 | if(o.labels){ |
---|
172 | labels = arr.map(this.series, function(s){ |
---|
173 | return s.name; |
---|
174 | }, this); |
---|
175 | shift = df.foldl1(df.map(labels, function(label){ |
---|
176 | var font = t.series.font; |
---|
177 | return g._base._getTextBox(label, { |
---|
178 | font: font |
---|
179 | }).w; |
---|
180 | }, this), "Math.max(a, b)") / 2; |
---|
181 | r = Math.min(rx - 2 * shift, ry - asize) + lboffset; |
---|
182 | labelR = r - lboffset; |
---|
183 | } |
---|
184 | if("radius" in o){ |
---|
185 | r = o.radius; |
---|
186 | labelR = r - lboffset; |
---|
187 | } |
---|
188 | r /= (1+axisExtra); |
---|
189 | var circle = { |
---|
190 | cx: offsets.l + rx, |
---|
191 | cy: offsets.t + ry, |
---|
192 | r: r |
---|
193 | }; |
---|
194 | |
---|
195 | for (i = this.series.length - 1; i >= 0; i--){ |
---|
196 | serieEntry = this.series[i]; |
---|
197 | if(!this.dirty && !serieEntry.dirty){ |
---|
198 | t.skip(); |
---|
199 | continue; |
---|
200 | } |
---|
201 | serieEntry.cleanGroup(); |
---|
202 | run = serieEntry.data; |
---|
203 | if(run !== null){ |
---|
204 | len = this._getObjectLength(run); |
---|
205 | //construct connect points |
---|
206 | if(!outerPoints || outerPoints.length <= 0){ |
---|
207 | outerPoints = [], innerPoints = [], labelPoints = []; |
---|
208 | this._buildPoints(outerPoints, len, circle, r, start, true, dim); |
---|
209 | this._buildPoints(innerPoints, len, circle, r*ro, start, true, dim); |
---|
210 | this._buildPoints(labelPoints, len, circle, labelR, start, false, dim); |
---|
211 | if(dv > 2){ |
---|
212 | divisionPoints = [], divisionRadius = []; |
---|
213 | for (j = 0; j < dv - 2; j++){ |
---|
214 | divisionPoints[j] = []; |
---|
215 | this._buildPoints(divisionPoints[j], len, circle, r*(ro + (1-ro)*(j+1)/(dv-1)), start, true, dim); |
---|
216 | divisionRadius[j] = r*(ro + (1-ro)*(j+1)/(dv-1)); |
---|
217 | } |
---|
218 | } |
---|
219 | } |
---|
220 | } |
---|
221 | } |
---|
222 | |
---|
223 | //draw Spider |
---|
224 | //axis |
---|
225 | var axisGroup = s.createGroup(), axisStroke = {color: axisColor, width: axisWidth}, |
---|
226 | spiderStroke = {color: spiderColor, width: spiderWidth}; |
---|
227 | for (j = outerPoints.length - 1; j >= 0; --j){ |
---|
228 | point = outerPoints[j]; |
---|
229 | var st = { |
---|
230 | x: point.x + (point.x - circle.cx) * axisExtra, |
---|
231 | y: point.y + (point.y - circle.cy) * axisExtra |
---|
232 | }, |
---|
233 | nd = { |
---|
234 | x: point.x + (point.x - circle.cx) * axisExtra / 2, |
---|
235 | y: point.y + (point.y - circle.cy) * axisExtra / 2 |
---|
236 | }; |
---|
237 | axisGroup.createLine({ |
---|
238 | x1: circle.cx, |
---|
239 | y1: circle.cy, |
---|
240 | x2: st.x, |
---|
241 | y2: st.y |
---|
242 | }).setStroke(axisStroke); |
---|
243 | //arrow |
---|
244 | this._drawArrow(axisGroup, st, nd, axisStroke); |
---|
245 | } |
---|
246 | |
---|
247 | // draw the label |
---|
248 | var labelGroup = s.createGroup(); |
---|
249 | for (j = labelPoints.length - 1; j >= 0; --j){ |
---|
250 | point = labelPoints[j]; |
---|
251 | fontWidth = g._base._getTextBox(this.labelKey[j], {font: axisFont}).w || 0; |
---|
252 | render = this.opt.htmlLabels && g.renderer != "vml" ? "html" : "gfx"; |
---|
253 | var elem = da.createText[render](this.chart, labelGroup, (!domGeom.isBodyLtr() && render == "html") ? (point.x + fontWidth - dim.width) : point.x, point.y, |
---|
254 | "middle", this.labelKey[j], axisFont, axisFontColor); |
---|
255 | if(this.opt.htmlLabels){ |
---|
256 | this.htmlElements.push(elem); |
---|
257 | } |
---|
258 | } |
---|
259 | |
---|
260 | //spider web: polygon or circle |
---|
261 | var spiderGroup = s.createGroup(); |
---|
262 | if(spt == "polygon"){ |
---|
263 | spiderGroup.createPolyline(outerPoints).setStroke(spiderStroke); |
---|
264 | spiderGroup.createPolyline(innerPoints).setStroke(spiderStroke); |
---|
265 | if(divisionPoints.length > 0){ |
---|
266 | for (j = divisionPoints.length - 1; j >= 0; --j){ |
---|
267 | spiderGroup.createPolyline(divisionPoints[j]).setStroke(spiderStroke); |
---|
268 | } |
---|
269 | } |
---|
270 | }else{//circle |
---|
271 | spiderGroup.createCircle({cx: circle.cx, cy: circle.cy, r: r}).setStroke(spiderStroke); |
---|
272 | spiderGroup.createCircle({cx: circle.cx, cy: circle.cy, r: r*ro}).setStroke(spiderStroke); |
---|
273 | if(divisionRadius.length > 0){ |
---|
274 | for (j = divisionRadius.length - 1; j >= 0; --j){ |
---|
275 | spiderGroup.createCircle({cx: circle.cx, cy: circle.cy, r: divisionRadius[j]}).setStroke(spiderStroke); |
---|
276 | } |
---|
277 | } |
---|
278 | } |
---|
279 | //text |
---|
280 | len = this._getObjectLength(this.datas); |
---|
281 | var textGroup = s.createGroup(), k = 0; |
---|
282 | for(var key in this.datas){ |
---|
283 | data = this.datas[key]; |
---|
284 | min = data.min; |
---|
285 | max = data.max; |
---|
286 | distance = max - min; |
---|
287 | end = start + 2 * Math.PI * k / len; |
---|
288 | for (i = 0; i < dv; i++){ |
---|
289 | var text = min + distance*i/(dv-1); |
---|
290 | point = this._getCoordinate(circle, r*(ro + (1-ro)*i/(dv-1)), end, dim); |
---|
291 | text = this._getLabel(text); |
---|
292 | fontWidth = g._base._getTextBox(text, {font: axisTickFont}).w || 0; |
---|
293 | render = this.opt.htmlLabels && g.renderer != "vml" ? "html" : "gfx"; |
---|
294 | if(this.opt.htmlLabels){ |
---|
295 | this.htmlElements.push(da.createText[render] |
---|
296 | (this.chart, textGroup, (!domGeom.isBodyLtr() && render == "html") ? (point.x + fontWidth - dim.width) : point.x, point.y, |
---|
297 | "start", text, axisTickFont, axisTickFontColor)); |
---|
298 | } |
---|
299 | } |
---|
300 | k++; |
---|
301 | } |
---|
302 | |
---|
303 | //draw series (animation) |
---|
304 | this.chart.seriesShapes = {}; |
---|
305 | for (i = this.series.length - 1; i >= 0; i--){ |
---|
306 | serieEntry = this.series[i]; |
---|
307 | run = serieEntry.data; |
---|
308 | if(run !== null){ |
---|
309 | //series polygon |
---|
310 | var seriePoints = [], tipData = []; |
---|
311 | k = 0; |
---|
312 | for(key in run){ |
---|
313 | data = this.datas[key]; |
---|
314 | min = data.min; |
---|
315 | max = data.max; |
---|
316 | distance = max - min; |
---|
317 | var entry = run[key], end = start + 2 * Math.PI * k / len; |
---|
318 | point = this._getCoordinate(circle, r*(ro + (1-ro)*(entry-min)/distance), end, dim); |
---|
319 | seriePoints.push(point); |
---|
320 | tipData.push({sname: serieEntry.name, key: key, data: entry}); |
---|
321 | k++; |
---|
322 | } |
---|
323 | seriePoints[seriePoints.length] = seriePoints[0]; |
---|
324 | tipData[tipData.length] = tipData[0]; |
---|
325 | var polygonBoundRect = this._getBoundary(seriePoints), |
---|
326 | theme = t.next("spider", [o, serieEntry]), ts = serieEntry.group, |
---|
327 | f = g.normalizeColor(theme.series.fill), sk = {color: theme.series.fill, width: seriesWidth}; |
---|
328 | f.a = o.seriesFillAlpha; |
---|
329 | serieEntry.dyn = {fill: f, stroke: sk}; |
---|
330 | |
---|
331 | var osps = this.oldSeriePoints[serieEntry.name]; |
---|
332 | var cs = this._createSeriesEntry(ts, (osps || innerPoints), seriePoints, f, sk, r, ro, ms, at); |
---|
333 | this.chart.seriesShapes[serieEntry.name] = cs; |
---|
334 | this.oldSeriePoints[serieEntry.name] = seriePoints; |
---|
335 | |
---|
336 | var po = { |
---|
337 | element: "spider_poly", |
---|
338 | index: i, |
---|
339 | id: "spider_poly_"+serieEntry.name, |
---|
340 | run: serieEntry, |
---|
341 | plot: this, |
---|
342 | shape: cs.poly, |
---|
343 | parent: ts, |
---|
344 | brect: polygonBoundRect, |
---|
345 | cx: circle.cx, |
---|
346 | cy: circle.cy, |
---|
347 | cr: r, |
---|
348 | f: f, |
---|
349 | s: s |
---|
350 | }; |
---|
351 | this._connectEvents(po); |
---|
352 | |
---|
353 | var so = { |
---|
354 | element: "spider_plot", |
---|
355 | index: i, |
---|
356 | id: "spider_plot_"+serieEntry.name, |
---|
357 | run: serieEntry, |
---|
358 | plot: this, |
---|
359 | shape: serieEntry.group |
---|
360 | }; |
---|
361 | this._connectEvents(so); |
---|
362 | |
---|
363 | arr.forEach(cs.circles, function(c, i){ |
---|
364 | var co = { |
---|
365 | element: "spider_circle", |
---|
366 | index: i, |
---|
367 | id: "spider_circle_"+serieEntry.name+i, |
---|
368 | run: serieEntry, |
---|
369 | plot: this, |
---|
370 | shape: c, |
---|
371 | parent: ts, |
---|
372 | tdata: tipData[i], |
---|
373 | cx: seriePoints[i].x, |
---|
374 | cy: seriePoints[i].y, |
---|
375 | f: f, |
---|
376 | s: s |
---|
377 | }; |
---|
378 | this._connectEvents(co); |
---|
379 | }, this); |
---|
380 | } |
---|
381 | } |
---|
382 | return this; // dojox/charting/plot2d/Spider |
---|
383 | }, |
---|
384 | _createSeriesEntry: function(ts, osps, sps, f, sk, r, ro, ms, at){ |
---|
385 | //polygon |
---|
386 | var spoly = ts.createPolyline(osps).setFill(f).setStroke(sk), scircle = []; |
---|
387 | for (var j = 0; j < osps.length; j++){ |
---|
388 | var point = osps[j], cr = ms; |
---|
389 | var circle = ts.createCircle({cx: point.x, cy: point.y, r: cr}).setFill(f).setStroke(sk); |
---|
390 | scircle.push(circle); |
---|
391 | } |
---|
392 | |
---|
393 | var anims = arr.map(sps, function(np, j){ |
---|
394 | // create animation |
---|
395 | var sp = osps[j], |
---|
396 | anim = new baseFx.Animation({ |
---|
397 | duration: 1000, |
---|
398 | easing: at, |
---|
399 | curve: [sp.y, np.y] |
---|
400 | }); |
---|
401 | var spl = spoly, sc = scircle[j]; |
---|
402 | hub.connect(anim, "onAnimate", function(y){ |
---|
403 | //apply poly |
---|
404 | var pshape = spl.getShape(); |
---|
405 | pshape.points[j].y = y; |
---|
406 | spl.setShape(pshape); |
---|
407 | //apply circle |
---|
408 | var cshape = sc.getShape(); |
---|
409 | cshape.cy = y; |
---|
410 | sc.setShape(cshape); |
---|
411 | }); |
---|
412 | return anim; |
---|
413 | }); |
---|
414 | |
---|
415 | var anims1 = arr.map(sps, function(np, j){ |
---|
416 | // create animation |
---|
417 | var sp = osps[j], |
---|
418 | anim = new baseFx.Animation({ |
---|
419 | duration: 1000, |
---|
420 | easing: at, |
---|
421 | curve: [sp.x, np.x] |
---|
422 | }); |
---|
423 | var spl = spoly, sc = scircle[j]; |
---|
424 | hub.connect(anim, "onAnimate", function(x){ |
---|
425 | //apply poly |
---|
426 | var pshape = spl.getShape(); |
---|
427 | pshape.points[j].x = x; |
---|
428 | spl.setShape(pshape); |
---|
429 | //apply circle |
---|
430 | var cshape = sc.getShape(); |
---|
431 | cshape.cx = x; |
---|
432 | sc.setShape(cshape); |
---|
433 | }); |
---|
434 | return anim; |
---|
435 | }); |
---|
436 | var masterAnimation = coreFx.combine(anims.concat(anims1)); //dojo.fx.chain(anims); |
---|
437 | masterAnimation.play(); |
---|
438 | return {group :ts, poly: spoly, circles: scircle}; |
---|
439 | }, |
---|
440 | plotEvent: function(o){ |
---|
441 | // summary: |
---|
442 | // Stub function for use by specific plots. |
---|
443 | // o: Object |
---|
444 | // An object intended to represent event parameters. |
---|
445 | if(o.element == "spider_plot"){ |
---|
446 | //dojo gfx function "moveToFront" not work in IE |
---|
447 | if(o.type == "onmouseover" && !has("ie")){ |
---|
448 | o.shape.moveToFront(); |
---|
449 | } |
---|
450 | } |
---|
451 | }, |
---|
452 | |
---|
453 | tooltipFunc: function(o){ |
---|
454 | if(o.element == "spider_circle"){ |
---|
455 | return o.tdata.sname + "<br/>" + o.tdata.key + "<br/>" + o.tdata.data; |
---|
456 | }else{ |
---|
457 | return null; |
---|
458 | } |
---|
459 | }, |
---|
460 | |
---|
461 | _getBoundary: function(points){ |
---|
462 | var xmax = points[0].x, |
---|
463 | xmin = points[0].x, |
---|
464 | ymax = points[0].y, |
---|
465 | ymin = points[0].y; |
---|
466 | for(var i = 0; i < points.length; i++){ |
---|
467 | var point = points[i]; |
---|
468 | xmax = Math.max(point.x, xmax); |
---|
469 | ymax = Math.max(point.y, ymax); |
---|
470 | xmin = Math.min(point.x, xmin); |
---|
471 | ymin = Math.min(point.y, ymin); |
---|
472 | } |
---|
473 | return { |
---|
474 | x: xmin, |
---|
475 | y: ymin, |
---|
476 | width: xmax - xmin, |
---|
477 | height: ymax - ymin |
---|
478 | }; |
---|
479 | }, |
---|
480 | |
---|
481 | _drawArrow: function(s, start, end, stroke){ |
---|
482 | var len = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2)), |
---|
483 | sin = (end.y - start.y)/len, cos = (end.x - start.x)/len, |
---|
484 | point2 = {x: end.x + (len/3)*(-sin), y: end.y + (len/3)*cos}, |
---|
485 | point3 = {x: end.x + (len/3)*sin, y: end.y + (len/3)*(-cos)}; |
---|
486 | s.createPolyline([start, point2, point3]).setFill(stroke.color).setStroke(stroke); |
---|
487 | }, |
---|
488 | |
---|
489 | _buildPoints: function(points, count, circle, radius, angle, recursive, dim){ |
---|
490 | for(var i = 0; i < count; i++){ |
---|
491 | var end = angle + 2 * Math.PI * i / count; |
---|
492 | points.push(this._getCoordinate(circle, radius, end, dim)); |
---|
493 | } |
---|
494 | if(recursive){ |
---|
495 | points.push(this._getCoordinate(circle, radius, angle + 2 * Math.PI, dim)); |
---|
496 | } |
---|
497 | }, |
---|
498 | |
---|
499 | _getCoordinate: function(circle, radius, angle, dim){ |
---|
500 | var x = circle.cx + radius * Math.cos(angle); |
---|
501 | if(has("dojo-bidi") && this.chart.isRightToLeft() && dim){ |
---|
502 | x = dim.width - x; |
---|
503 | } |
---|
504 | return { |
---|
505 | x: x, |
---|
506 | y: circle.cy + radius * Math.sin(angle) |
---|
507 | } |
---|
508 | }, |
---|
509 | |
---|
510 | _getObjectLength: function(obj){ |
---|
511 | var count = 0; |
---|
512 | if(lang.isObject(obj)){ |
---|
513 | for(var key in obj){ |
---|
514 | count++; |
---|
515 | } |
---|
516 | } |
---|
517 | return count; |
---|
518 | }, |
---|
519 | |
---|
520 | // utilities |
---|
521 | _getLabel: function(number){ |
---|
522 | return dc.getLabel(number, this.opt.fixed, this.opt.precision); |
---|
523 | } |
---|
524 | }); |
---|
525 | |
---|
526 | return Spider; // dojox/plot2d/Spider |
---|
527 | }); |
---|