rgraph-rails 1.0.7 → 1.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/lib/rgraph-rails/version.rb +1 -1
- data/license.txt +4 -16
- data/vendor/assets/javascripts/RGraph.bar.js +3734 -241
- data/vendor/assets/javascripts/RGraph.bipolar.js +2005 -115
- data/vendor/assets/javascripts/RGraph.common.annotate.js +395 -35
- data/vendor/assets/javascripts/RGraph.common.context.js +595 -30
- data/vendor/assets/javascripts/RGraph.common.core.js +5282 -405
- data/vendor/assets/javascripts/RGraph.common.csv.js +276 -19
- data/vendor/assets/javascripts/RGraph.common.deprecated.js +450 -35
- data/vendor/assets/javascripts/RGraph.common.dynamic.js +1395 -86
- data/vendor/assets/javascripts/RGraph.common.effects.js +1545 -90
- data/vendor/assets/javascripts/RGraph.common.key.js +753 -54
- data/vendor/assets/javascripts/RGraph.common.resizing.js +563 -37
- data/vendor/assets/javascripts/RGraph.common.sheets.js +352 -29
- data/vendor/assets/javascripts/RGraph.common.tooltips.js +450 -32
- data/vendor/assets/javascripts/RGraph.common.zoom.js +219 -14
- data/vendor/assets/javascripts/RGraph.drawing.background.js +570 -35
- data/vendor/assets/javascripts/RGraph.drawing.circle.js +544 -35
- data/vendor/assets/javascripts/RGraph.drawing.image.js +755 -52
- data/vendor/assets/javascripts/RGraph.drawing.marker1.js +645 -41
- data/vendor/assets/javascripts/RGraph.drawing.marker2.js +633 -37
- data/vendor/assets/javascripts/RGraph.drawing.marker3.js +514 -36
- data/vendor/assets/javascripts/RGraph.drawing.poly.js +559 -39
- data/vendor/assets/javascripts/RGraph.drawing.rect.js +548 -35
- data/vendor/assets/javascripts/RGraph.drawing.text.js +664 -36
- data/vendor/assets/javascripts/RGraph.drawing.xaxis.js +812 -50
- data/vendor/assets/javascripts/RGraph.drawing.yaxis.js +856 -51
- data/vendor/assets/javascripts/RGraph.fuel.js +964 -58
- data/vendor/assets/javascripts/RGraph.funnel.js +984 -55
- data/vendor/assets/javascripts/RGraph.gantt.js +1354 -77
- data/vendor/assets/javascripts/RGraph.gauge.js +1421 -87
- data/vendor/assets/javascripts/RGraph.hbar.js +2562 -146
- data/vendor/assets/javascripts/RGraph.hprogress.js +1401 -80
- data/vendor/assets/javascripts/RGraph.line.js +4226 -244
- data/vendor/assets/javascripts/RGraph.meter.js +1280 -74
- data/vendor/assets/javascripts/RGraph.modaldialog.js +301 -19
- data/vendor/assets/javascripts/RGraph.odo.js +1264 -71
- data/vendor/assets/javascripts/RGraph.pie.js +2288 -137
- data/vendor/assets/javascripts/RGraph.radar.js +1847 -110
- data/vendor/assets/javascripts/RGraph.rose.js +1977 -108
- data/vendor/assets/javascripts/RGraph.rscatter.js +1432 -80
- data/vendor/assets/javascripts/RGraph.scatter.js +3036 -168
- data/vendor/assets/javascripts/RGraph.semicircularprogress.js +1120 -60
- data/vendor/assets/javascripts/RGraph.svg.bar.js +1067 -0
- data/vendor/assets/javascripts/RGraph.svg.common.ajax.js +247 -0
- data/vendor/assets/javascripts/RGraph.svg.common.core.js +3363 -0
- data/vendor/assets/javascripts/RGraph.svg.common.csv.js +277 -0
- data/vendor/assets/javascripts/RGraph.svg.common.fx.js +1304 -0
- data/vendor/assets/javascripts/RGraph.svg.common.sheets.js +353 -0
- data/vendor/assets/javascripts/RGraph.svg.common.tooltips.js +233 -0
- data/vendor/assets/javascripts/RGraph.svg.hbar.js +1141 -0
- data/vendor/assets/javascripts/RGraph.svg.line.js +1486 -0
- data/vendor/assets/javascripts/RGraph.svg.pie.js +781 -0
- data/vendor/assets/javascripts/RGraph.svg.radar.js +1326 -0
- data/vendor/assets/javascripts/RGraph.svg.semicircularprogress.js +817 -0
- data/vendor/assets/javascripts/RGraph.thermometer.js +1135 -62
- data/vendor/assets/javascripts/RGraph.vprogress.js +1470 -83
- data/vendor/assets/javascripts/RGraph.waterfall.js +1347 -80
- metadata +15 -3
@@ -0,0 +1,1326 @@
|
|
1
|
+
// version: 2017-01-02
|
2
|
+
/**
|
3
|
+
* o--------------------------------------------------------------------------------o
|
4
|
+
* | This file is part of the RGraph package - you can learn more at: |
|
5
|
+
* | |
|
6
|
+
* | http://www.rgraph.net |
|
7
|
+
* | |
|
8
|
+
* | RGraph is licensed under the Open Source MIT license. That means that it's |
|
9
|
+
* | totally free to use! |
|
10
|
+
* o--------------------------------------------------------------------------------o
|
11
|
+
*/
|
12
|
+
|
13
|
+
RGraph = window.RGraph || {isRGraph: true};
|
14
|
+
RGraph.SVG = RGraph.SVG || {};
|
15
|
+
|
16
|
+
// Module pattern
|
17
|
+
(function (win, doc, undefined)
|
18
|
+
{
|
19
|
+
var RG = RGraph,
|
20
|
+
ua = navigator.userAgent,
|
21
|
+
ma = Math,
|
22
|
+
win = window,
|
23
|
+
doc = document;
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
RG.SVG.Radar = function (conf)
|
28
|
+
{
|
29
|
+
this.id = conf.id;
|
30
|
+
this.uid = RG.SVG.createUID();
|
31
|
+
this.container = document.getElementById(this.id);
|
32
|
+
this.svg = RG.SVG.createSVG({container: this.container});
|
33
|
+
this.isRGraph = true;
|
34
|
+
this.width = Number(this.svg.getAttribute('width'));
|
35
|
+
this.height = Number(this.svg.getAttribute('height'));
|
36
|
+
this.data = RG.SVG.arrayClone(conf.data);
|
37
|
+
this.originalData = RG.SVG.arrayClone(conf.data);
|
38
|
+
this.type = 'radar';
|
39
|
+
this.coords = [];
|
40
|
+
this.coords2 = [];
|
41
|
+
this.angles = [];
|
42
|
+
this.angles2 = [];
|
43
|
+
this.colorsParsed = false;
|
44
|
+
this.originalColors = {};
|
45
|
+
this.gradientCounter = 1;
|
46
|
+
this.nodes = [];
|
47
|
+
this.shadowNodes = [];
|
48
|
+
this.max = 0;
|
49
|
+
this.redraw = false;
|
50
|
+
this.highlight_hotspot = null;
|
51
|
+
|
52
|
+
// Add this object to the ObjectRegistry
|
53
|
+
RG.SVG.OR.add(this);
|
54
|
+
|
55
|
+
// Set the DIV container to be inline-block
|
56
|
+
this.container.style.display = 'inline-block';
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
this.properties =
|
63
|
+
{
|
64
|
+
centerx: null,
|
65
|
+
centery: null,
|
66
|
+
radius: null,
|
67
|
+
|
68
|
+
gutterLeft: 35,
|
69
|
+
gutterRight: 35,
|
70
|
+
gutterTop: 35,
|
71
|
+
gutterBottom: 35,
|
72
|
+
|
73
|
+
backgroundGrid: true,
|
74
|
+
backgroundGridColor: '#ddd',
|
75
|
+
backgroundGridRadialsCount: null,
|
76
|
+
backgroundGridConcentricsCount: 5,
|
77
|
+
backgroundGridLinewidth: 1,
|
78
|
+
|
79
|
+
colors: [
|
80
|
+
'red', 'black', 'orange', 'green', '#6ff', '#ccc',
|
81
|
+
'pink', 'orange', 'cyan', 'maroon', 'olive', 'teal'
|
82
|
+
],
|
83
|
+
filled: false,
|
84
|
+
filledOpacity: 0.25,
|
85
|
+
filledAccumulative: true,
|
86
|
+
|
87
|
+
textColor: 'black',
|
88
|
+
textFont: 'sans-serif',
|
89
|
+
textSize: 12,
|
90
|
+
textBold: false,
|
91
|
+
textItalic: false,
|
92
|
+
|
93
|
+
labels: [],
|
94
|
+
|
95
|
+
scaleVisible: true,
|
96
|
+
scaleUnitsPre: '',
|
97
|
+
scaleUnitsPost: '',
|
98
|
+
scaleMax: null,
|
99
|
+
scaleMin: 0,
|
100
|
+
scalePoint: '.',
|
101
|
+
scaleThousand: ',',
|
102
|
+
scaleRound: false,
|
103
|
+
scaleDecimals: 0,
|
104
|
+
scaleFormatter: null,
|
105
|
+
scaleBold: null,
|
106
|
+
scaleItalic: null,
|
107
|
+
scaleColor: null,
|
108
|
+
scaleSize: null,
|
109
|
+
scaleFont: null,
|
110
|
+
scaleLabelsCount: 5,
|
111
|
+
|
112
|
+
linewidth: 1,
|
113
|
+
|
114
|
+
tooltips: null,
|
115
|
+
tooltipsOverride: null,
|
116
|
+
tooltipsEffect: 'fade',
|
117
|
+
tooltipsCssClass: 'RGraph_tooltip',
|
118
|
+
tooltipsEvent: 'mousemove',
|
119
|
+
|
120
|
+
highlightStroke: 'rgba(0,0,0,0)',
|
121
|
+
highlightFill: 'rgba(255,255,255,0.7)',
|
122
|
+
highlightLinewidth: 1,
|
123
|
+
|
124
|
+
tickmarks: 'circle',
|
125
|
+
tickmarksLinewidth: 1,
|
126
|
+
tickmarksSize: 6,
|
127
|
+
tickmarksFill: 'white',
|
128
|
+
|
129
|
+
title: '',
|
130
|
+
titleSize: 16,
|
131
|
+
titleX: null,
|
132
|
+
titleY: null,
|
133
|
+
titleHalign: 'center',
|
134
|
+
titleValign: 'bottom',
|
135
|
+
titleColor: 'black',
|
136
|
+
titleFont: null,
|
137
|
+
titleBold: false,
|
138
|
+
titleItalic: false,
|
139
|
+
|
140
|
+
titleSubtitle: '',
|
141
|
+
titleSubtitleSize: 10,
|
142
|
+
titleSubtitleX: null,
|
143
|
+
titleSubtitleY: null,
|
144
|
+
titleSubtitleHalign: 'center',
|
145
|
+
titleSubtitleValign: 'top',
|
146
|
+
titleSubtitleColor: '#aaa',
|
147
|
+
titleSubtitleFont: null,
|
148
|
+
titleSubtitleBold: false,
|
149
|
+
titleSubtitleItalic: false,
|
150
|
+
|
151
|
+
grouping: 'normal', // Can also be stcked
|
152
|
+
|
153
|
+
shadow: false,
|
154
|
+
shadowOffsetx: 2,
|
155
|
+
shadowOffsety: 2,
|
156
|
+
shadowBlur: 2,
|
157
|
+
shadowOpacity: 0.25,
|
158
|
+
|
159
|
+
attribution: true,
|
160
|
+
attributionX: null,
|
161
|
+
attributionY: null,
|
162
|
+
attributionHref: 'http://www.rgraph.net/svg/index.html',
|
163
|
+
attributionHalign: 'right',
|
164
|
+
attributionValign: 'bottom',
|
165
|
+
attributionSize: 8,
|
166
|
+
attributionColor: 'gray',
|
167
|
+
attributionFont: 'sans-serif',
|
168
|
+
attributionItalic: false,
|
169
|
+
attributionBold: false
|
170
|
+
};
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
/**
|
178
|
+
* "Decorate" the object with the generic effects if the effects library has been included
|
179
|
+
*/
|
180
|
+
if (RG.SVG.FX && typeof RG.SVG.FX.decorate === 'function') {
|
181
|
+
RG.SVG.FX.decorate(this);
|
182
|
+
}
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
var prop = this.properties;
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
//
|
193
|
+
// A setter that the constructor uses (at the end)
|
194
|
+
// to set all of the properties
|
195
|
+
//
|
196
|
+
// @param string name The name of the property to set
|
197
|
+
// @param string value The value to set the property to
|
198
|
+
//
|
199
|
+
this.set = function (name, value)
|
200
|
+
{
|
201
|
+
if (arguments.length === 1 && typeof name === 'object') {
|
202
|
+
for (i in arguments[0]) {
|
203
|
+
if (typeof i === 'string') {
|
204
|
+
this.set(i, arguments[0][i]);
|
205
|
+
}
|
206
|
+
}
|
207
|
+
} else {
|
208
|
+
this.properties[name] = value;
|
209
|
+
}
|
210
|
+
|
211
|
+
return this;
|
212
|
+
};
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
//
|
222
|
+
// The draw method draws the Bar chart
|
223
|
+
//
|
224
|
+
this.draw = function ()
|
225
|
+
{
|
226
|
+
// Fire the beforedraw event
|
227
|
+
RG.SVG.fireCustomEvent(this, 'onbeforedraw');
|
228
|
+
|
229
|
+
|
230
|
+
|
231
|
+
// Reset the data back to the original values
|
232
|
+
this.data = RG.SVG.arrayClone(this.originalData);
|
233
|
+
|
234
|
+
//
|
235
|
+
// The datasets have to have the same number of elements
|
236
|
+
//
|
237
|
+
if (this.data.length > 1) {
|
238
|
+
|
239
|
+
var len = this.data[0].length;
|
240
|
+
|
241
|
+
for (var i=1; i<this.data.length; ++i) {
|
242
|
+
if (this.data[i].length !== len) {
|
243
|
+
alert('[ERROR] The Radar chart datasets must have the same number of elements!');
|
244
|
+
}
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
|
249
|
+
|
250
|
+
// Reset the coords array to stop them growing
|
251
|
+
this.angles = [];
|
252
|
+
this.coords = [];
|
253
|
+
this.coords2 = [];
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
// Create the defs tag if necessary
|
260
|
+
RG.SVG.createDefs(this);
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
this.graphWidth = this.width - prop.gutterLeft - prop.gutterRight;
|
266
|
+
this.graphHeight = this.height - prop.gutterTop - prop.gutterBottom;
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
// Work out the center point
|
271
|
+
this.centerx = (this.graphWidth / 2) + prop.gutterLeft;
|
272
|
+
this.centery = (this.graphHeight / 2) + prop.gutterTop;
|
273
|
+
this.radius = ma.min(this.graphWidth, this.graphHeight) / 2;
|
274
|
+
|
275
|
+
|
276
|
+
|
277
|
+
// Allow the user to override the calculated centerx/y/radius
|
278
|
+
this.centerx = typeof prop.centerx === 'number' ? prop.centerx : this.centerx;
|
279
|
+
this.centery = typeof prop.centery === 'number' ? prop.centery : this.centery;
|
280
|
+
this.radius = typeof prop.radius === 'number' ? prop.radius : this.radius;
|
281
|
+
|
282
|
+
//
|
283
|
+
// Allow the centerx/centery/radius to be a plus/minus
|
284
|
+
//
|
285
|
+
if (typeof prop.radius === 'string' && prop.radius.match(/^\+|-\d+$/) ) this.radius += parseFloat(prop.radius);
|
286
|
+
if (typeof prop.centerx === 'string' && prop.centerx.match(/^\+|-\d+$/) ) this.centery += parseFloat(prop.centerx);
|
287
|
+
if (typeof prop.centery === 'string' && prop.centery.match(/^\+|-\d+$/) ) this.centerx += parseFloat(prop.centery);
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
/**
|
294
|
+
* Add the data to the .originalData array and work out the max value
|
295
|
+
*
|
296
|
+
* 2/5/14 Now also use this loop to ensure that the data pieces
|
297
|
+
* are numbers
|
298
|
+
*/
|
299
|
+
if (RG.SVG.isArray(this.data) && (typeof this.data[0] === 'number' || typeof this.data[0] === 'string')) {
|
300
|
+
this.data = [this.data];
|
301
|
+
}
|
302
|
+
|
303
|
+
// Convert strings to numbers
|
304
|
+
for (var i=0; i<this.data.length; ++i) {
|
305
|
+
|
306
|
+
for (var j=0; j<this.data[i].length; ++j) {
|
307
|
+
|
308
|
+
if (typeof this.data[i][j] === 'string') {
|
309
|
+
this.data[i][j] = RG.SVG.stringsToNumbers(this.data[i][j]);
|
310
|
+
}
|
311
|
+
}
|
312
|
+
}
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
|
319
|
+
// Modify the datasets to represent the stacked data
|
320
|
+
// (if its stacked)
|
321
|
+
if (prop.filled && prop.filledAccumulative) {
|
322
|
+
for (var dataset=1; dataset<this.data.length; ++dataset) {
|
323
|
+
for (var i=0; i<this.data[dataset].length; ++i) {
|
324
|
+
this.data[dataset][i] += this.data[dataset - 1][i];
|
325
|
+
}
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
|
330
|
+
|
331
|
+
|
332
|
+
|
333
|
+
// Get the max value
|
334
|
+
this.getMaxValue();
|
335
|
+
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
|
340
|
+
|
341
|
+
|
342
|
+
/**
|
343
|
+
* Parse the colors. This allows for simple gradient syntax
|
344
|
+
*
|
345
|
+
* ** must be after the cx/cy/r has been calcuated **
|
346
|
+
*/
|
347
|
+
if (!this.colorsParsed) {
|
348
|
+
this.parseColors();
|
349
|
+
|
350
|
+
// Don't want to do this again
|
351
|
+
this.colorsParsed = true;
|
352
|
+
}
|
353
|
+
|
354
|
+
//
|
355
|
+
// Get the scale
|
356
|
+
//
|
357
|
+
|
358
|
+
this.scale = RG.SVG.getScale({
|
359
|
+
object: this,
|
360
|
+
numlabels: typeof prop.scaleLabelsCount === 'number' ? prop.scaleLabelsCount : prop.backgroundGridConcentricCount,
|
361
|
+
unitsPre: prop.scaleUnitsPre,
|
362
|
+
unitsPost: prop.scaleUnitsPost,
|
363
|
+
max: typeof prop.scaleMax === 'number' ? prop.scaleMax : this.max,
|
364
|
+
min: prop.scaleMin,
|
365
|
+
point: prop.scalePoint,
|
366
|
+
round: prop.scaleRound,
|
367
|
+
thousand: prop.scaleThousand,
|
368
|
+
decimals: prop.scaleDecimals,
|
369
|
+
strict: typeof prop.scaleMax === 'number',
|
370
|
+
formatter: prop.scaleFormatter
|
371
|
+
});
|
372
|
+
|
373
|
+
this.max = this.scale.max;
|
374
|
+
|
375
|
+
|
376
|
+
|
377
|
+
// Draw the background 'grid'
|
378
|
+
this.drawBackground();
|
379
|
+
|
380
|
+
|
381
|
+
|
382
|
+
// Draw the chart
|
383
|
+
this.drawRadar();
|
384
|
+
|
385
|
+
|
386
|
+
|
387
|
+
// Draw the tickmarks for the chart
|
388
|
+
this.drawTickmarks();
|
389
|
+
|
390
|
+
|
391
|
+
|
392
|
+
// Draw the labels
|
393
|
+
this.drawLabels();
|
394
|
+
|
395
|
+
|
396
|
+
|
397
|
+
// Draw the title and subtitle
|
398
|
+
RG.SVG.drawTitle(this);
|
399
|
+
|
400
|
+
|
401
|
+
|
402
|
+
// Add the tooltip hotspots
|
403
|
+
this.addTooltipHotspots();
|
404
|
+
|
405
|
+
|
406
|
+
|
407
|
+
|
408
|
+
// Add the attribution link. If you're adding this elsewhere on your page/site
|
409
|
+
// and you don't want it displayed then there are options available to not
|
410
|
+
// show it.
|
411
|
+
RG.SVG.attribution(this);
|
412
|
+
|
413
|
+
// Create the shadow definition if needed
|
414
|
+
if (prop.shadow) {
|
415
|
+
RG.SVG.setShadow({
|
416
|
+
object: this,
|
417
|
+
offsetx: prop.shadowOffsetx,
|
418
|
+
offsety: prop.shadowOffsety,
|
419
|
+
blur: prop.shadowBlur,
|
420
|
+
opacity: prop.shadowOpacity,
|
421
|
+
id: 'dropShadow'
|
422
|
+
});
|
423
|
+
}
|
424
|
+
|
425
|
+
|
426
|
+
|
427
|
+
// Add the event listener that clears the highlight if
|
428
|
+
// there is any. Must be MOUSEDOWN (ie before the click event)
|
429
|
+
var obj = this;
|
430
|
+
document.body.addEventListener('mousedown', function (e)
|
431
|
+
{
|
432
|
+
RG.SVG.removeHighlight(obj);
|
433
|
+
}, false);
|
434
|
+
|
435
|
+
|
436
|
+
|
437
|
+
// Fire the draw event
|
438
|
+
RG.SVG.fireCustomEvent(this, 'ondraw');
|
439
|
+
|
440
|
+
|
441
|
+
|
442
|
+
return this;
|
443
|
+
};
|
444
|
+
|
445
|
+
|
446
|
+
|
447
|
+
|
448
|
+
|
449
|
+
|
450
|
+
|
451
|
+
|
452
|
+
//
|
453
|
+
// Draw the background grid
|
454
|
+
//
|
455
|
+
this.drawBackground = function ()
|
456
|
+
{
|
457
|
+
if (prop.backgroundGrid) {
|
458
|
+
|
459
|
+
// Create the background grid group tag
|
460
|
+
var grid = RG.SVG.create({
|
461
|
+
svg: this.svg,
|
462
|
+
type: 'g',
|
463
|
+
attr: {
|
464
|
+
className: 'rgraph_radar_grid',
|
465
|
+
fill: 'rgba(0,0,0,0)',
|
466
|
+
stroke: prop.backgroundGridColor
|
467
|
+
}
|
468
|
+
});
|
469
|
+
|
470
|
+
// Draw the concentric "rings" grid lines that are
|
471
|
+
// arranged around the centerx/centery
|
472
|
+
|
473
|
+
var origin = 0 - (RG.SVG.TRIG.PI / 2),
|
474
|
+
radials = (typeof prop.backgroundGridRadialsCount === 'number' ? prop.backgroundGridRadialsCount : this.data[0].length),
|
475
|
+
concentrics = prop.backgroundGridConcentricsCount,
|
476
|
+
step = RG.SVG.TRIG.TWOPI / radials;
|
477
|
+
|
478
|
+
|
479
|
+
|
480
|
+
|
481
|
+
|
482
|
+
// First draw the radial lines that emanate from the
|
483
|
+
// center outwards
|
484
|
+
if (radials > 0) {
|
485
|
+
|
486
|
+
for (var i=0,len=radials; i<len; ++i) {
|
487
|
+
|
488
|
+
var coords = RG.SVG.TRIG.toCartesian({
|
489
|
+
cx: this.centerx,
|
490
|
+
cy: this.centery,
|
491
|
+
r: this.radius,
|
492
|
+
angle: origin + (i * step)
|
493
|
+
});
|
494
|
+
|
495
|
+
var str = 'M {1} {2} L {3} {4}'.format(
|
496
|
+
this.centerx,
|
497
|
+
this.centery,
|
498
|
+
coords.x,
|
499
|
+
coords.y
|
500
|
+
);
|
501
|
+
|
502
|
+
RG.SVG.create({
|
503
|
+
svg: this.svg,
|
504
|
+
type: 'path',
|
505
|
+
parent: grid,
|
506
|
+
attr: {
|
507
|
+
d: str,
|
508
|
+
stroke: prop.backgroundGridColor,
|
509
|
+
'stroke-width': prop.backgroundGridLinewidth
|
510
|
+
}
|
511
|
+
});
|
512
|
+
}
|
513
|
+
}
|
514
|
+
|
515
|
+
|
516
|
+
|
517
|
+
|
518
|
+
|
519
|
+
// Draw the concentrics
|
520
|
+
if (concentrics > 0) {
|
521
|
+
for (var j=1; j<=concentrics; j++) {
|
522
|
+
for (var i=0,len=radials,path=[]; i<len; ++i) {
|
523
|
+
|
524
|
+
var coords = RG.SVG.TRIG.toCartesian({
|
525
|
+
cx: this.centerx,
|
526
|
+
cy: this.centery,
|
527
|
+
r: this.radius * (j/concentrics),
|
528
|
+
angle: origin + (i * step)
|
529
|
+
});
|
530
|
+
|
531
|
+
path.push('{1} {2} {3}'.format(
|
532
|
+
i === 0 ? 'M' : 'L',
|
533
|
+
coords.x,
|
534
|
+
coords.y
|
535
|
+
));
|
536
|
+
|
537
|
+
}
|
538
|
+
|
539
|
+
// Now add the path to the scene
|
540
|
+
RG.SVG.create({
|
541
|
+
svg: this.svg,
|
542
|
+
type: 'path',
|
543
|
+
parent: grid,
|
544
|
+
attr: {
|
545
|
+
d: path.join(' ') + ' z',
|
546
|
+
fill: 'transparent',
|
547
|
+
stroke: prop.backgroundGridColor,
|
548
|
+
'stroke-width': prop.backgroundGridLinewidth
|
549
|
+
}
|
550
|
+
});
|
551
|
+
}
|
552
|
+
}
|
553
|
+
}
|
554
|
+
};
|
555
|
+
|
556
|
+
|
557
|
+
|
558
|
+
|
559
|
+
|
560
|
+
|
561
|
+
|
562
|
+
|
563
|
+
//
|
564
|
+
// Draws the radar
|
565
|
+
//
|
566
|
+
this.drawRadar = function (opt)
|
567
|
+
{
|
568
|
+
for (var dataset=0,len=this.data.length; dataset<len; ++dataset) {
|
569
|
+
|
570
|
+
// Ensure these exist
|
571
|
+
this.coords2[dataset] = [];
|
572
|
+
this.angles2[dataset] = [];
|
573
|
+
|
574
|
+
// Initialise the path
|
575
|
+
var path = [];
|
576
|
+
|
577
|
+
for (var i=0,len2=this.data[dataset].length; i<len2; ++i) {
|
578
|
+
|
579
|
+
var value = this.data[dataset][i];
|
580
|
+
|
581
|
+
var xy = RG.SVG.TRIG.toCartesian({
|
582
|
+
cx: this.centerx,
|
583
|
+
cy: this.centery,
|
584
|
+
r: this.getRadius(this.data[dataset][i]),
|
585
|
+
angle: (RG.SVG.TRIG.TWOPI / len2) * i - RG.SVG.TRIG.HALFPI
|
586
|
+
});
|
587
|
+
|
588
|
+
xy.r = (( (value - prop.scaleMin) / (this.max - prop.scaleMin) ) ) * this.radius;
|
589
|
+
xy.angle = (RG.SVG.TRIG.TWOPI / len2) * i - RG.SVG.TRIG.HALFPI;
|
590
|
+
|
591
|
+
path.push('{1}{2} {3}'.format(
|
592
|
+
i === 0 ? 'M' : 'L',
|
593
|
+
xy.x,
|
594
|
+
xy.y
|
595
|
+
));
|
596
|
+
|
597
|
+
// Save the coordinates and angle
|
598
|
+
this.angles.push({
|
599
|
+
cx: this.centerx,
|
600
|
+
cy: this.centery,
|
601
|
+
r: xy.r,
|
602
|
+
angle: xy.angle
|
603
|
+
});
|
604
|
+
this.angles2[dataset].push({
|
605
|
+
cx: this.centerx,
|
606
|
+
cy: this.centery,
|
607
|
+
r: xy.r,
|
608
|
+
angle: xy.angle
|
609
|
+
});
|
610
|
+
|
611
|
+
this.coords.push([
|
612
|
+
xy.x,
|
613
|
+
xy.y
|
614
|
+
]);
|
615
|
+
this.coords2[dataset].push([
|
616
|
+
xy.x,
|
617
|
+
xy.y
|
618
|
+
]);
|
619
|
+
}
|
620
|
+
|
621
|
+
// If a stacked filled charts then add the reverse path
|
622
|
+
if (dataset > 0 && prop.filled && prop.filledAccumulative) {
|
623
|
+
|
624
|
+
// Add a line completing the "circle"
|
625
|
+
path.push('L {1} {2}'.format(
|
626
|
+
this.coords2[dataset][0][0],
|
627
|
+
this.coords2[dataset][0][1]
|
628
|
+
));
|
629
|
+
|
630
|
+
// Move to the previous dataset
|
631
|
+
path.push('M {1} {2}'.format(
|
632
|
+
this.coords2[dataset - 1][0][0],
|
633
|
+
this.coords2[dataset - 1][0][1]
|
634
|
+
));
|
635
|
+
|
636
|
+
// Now backtrack over the previous dataset
|
637
|
+
for (var i=this.coords2[dataset - 1].length - 1; i>=0; --i) {
|
638
|
+
path.push('L {1} {2}'.format(
|
639
|
+
this.coords2[dataset - 1][i][0],
|
640
|
+
this.coords2[dataset - 1][i][1]
|
641
|
+
));
|
642
|
+
}
|
643
|
+
|
644
|
+
this.redraw = true;
|
645
|
+
|
646
|
+
} else {
|
647
|
+
// Add the closepath
|
648
|
+
path.push('z');
|
649
|
+
}
|
650
|
+
|
651
|
+
|
652
|
+
var path = RG.SVG.create({
|
653
|
+
svg: this.svg,
|
654
|
+
type: 'path',
|
655
|
+
attr: {
|
656
|
+
d: path.join(" "),
|
657
|
+
stroke: prop.colors[dataset],
|
658
|
+
fill: prop.filled ? prop.colors[dataset] : 'transparent',
|
659
|
+
'fill-opacity': prop.filledOpacity,
|
660
|
+
'stroke-width': prop.linewidth,
|
661
|
+
filter: prop.shadow ? 'url(#dropShadow)' : '',
|
662
|
+
}
|
663
|
+
});
|
664
|
+
|
665
|
+
path.setAttribute('data-dataset', dataset);
|
666
|
+
}
|
667
|
+
|
668
|
+
|
669
|
+
// Redraw the chart (this only runs if necessary
|
670
|
+
this.redrawRadar();
|
671
|
+
};
|
672
|
+
|
673
|
+
|
674
|
+
|
675
|
+
|
676
|
+
|
677
|
+
|
678
|
+
|
679
|
+
|
680
|
+
//
|
681
|
+
// Redraws the chart if required
|
682
|
+
//
|
683
|
+
this.redrawRadar = function ()
|
684
|
+
{
|
685
|
+
if (this.redraw) {
|
686
|
+
|
687
|
+
this.redraw = false;
|
688
|
+
|
689
|
+
// Loop through ths coordinates
|
690
|
+
for (var dataset = 0; dataset<this.coords2.length; ++dataset) {
|
691
|
+
|
692
|
+
var path = [];
|
693
|
+
|
694
|
+
for (var i=0; i<this.coords2[dataset].length; ++i) {
|
695
|
+
if (i === 0) {
|
696
|
+
path.push('M {1} {2}'.format(
|
697
|
+
this.coords2[dataset][i][0],
|
698
|
+
this.coords2[dataset][i][1]
|
699
|
+
));
|
700
|
+
} else {
|
701
|
+
path.push('L {1} {2}'.format(
|
702
|
+
this.coords2[dataset][i][0],
|
703
|
+
this.coords2[dataset][i][1]
|
704
|
+
))
|
705
|
+
}
|
706
|
+
}
|
707
|
+
|
708
|
+
path.push('z')
|
709
|
+
|
710
|
+
RG.SVG.create({
|
711
|
+
svg: this.svg,
|
712
|
+
type: 'path',
|
713
|
+
attr: {
|
714
|
+
d: path.join(" "),
|
715
|
+
stroke: prop.colors[dataset],
|
716
|
+
fill: 'transparent',
|
717
|
+
'stroke-width': prop.linewidth
|
718
|
+
}
|
719
|
+
});
|
720
|
+
}
|
721
|
+
}
|
722
|
+
};
|
723
|
+
|
724
|
+
|
725
|
+
|
726
|
+
|
727
|
+
|
728
|
+
|
729
|
+
|
730
|
+
|
731
|
+
//
|
732
|
+
// Draw the tickmarks
|
733
|
+
//
|
734
|
+
this.drawTickmarks = function ()
|
735
|
+
{
|
736
|
+
var group = RG.SVG.create({
|
737
|
+
svg: this.svg,
|
738
|
+
type: 'g',
|
739
|
+
attr: {
|
740
|
+
}
|
741
|
+
});
|
742
|
+
|
743
|
+
for (var i=0; i<this.coords2.length; ++i) {
|
744
|
+
for (var j=0; j<this.coords2[i].length; ++j) {
|
745
|
+
if (prop.tickmarks === 'circle' || prop.tickmarks === 'filledcircle' ) {
|
746
|
+
var c = RG.SVG.create({
|
747
|
+
svg: this.svg,
|
748
|
+
type: 'circle',
|
749
|
+
fparent: group,
|
750
|
+
attr: {
|
751
|
+
cx: this.coords2[i][j][0],
|
752
|
+
cy: this.coords2[i][j][1],
|
753
|
+
r: prop.tickmarksSize,
|
754
|
+
fill: prop.tickmarks === 'filledcircle' ? prop.colors[i] : prop.tickmarksFill,
|
755
|
+
stroke: prop.colors[i],
|
756
|
+
'stroke-width': prop.tickmarksLinewidth
|
757
|
+
}
|
758
|
+
});
|
759
|
+
|
760
|
+
c.setAttribute('data-dataset', i);
|
761
|
+
c.setAttribute('data-index', j);
|
762
|
+
|
763
|
+
|
764
|
+
} else if (prop.tickmarks === 'rect' || prop.tickmarks === 'filledrect') {
|
765
|
+
|
766
|
+
var halfTickmarkSize = prop.tickmarksSize / 2;
|
767
|
+
var fill = typeof prop.tickmarksFill === 'object' && prop.tickmarksFill[i] ? prop.tickmarksFill[i] : prop.tickmarksFill;
|
768
|
+
|
769
|
+
var s = RG.SVG.create({
|
770
|
+
svg: this.svg,
|
771
|
+
type: 'rect',
|
772
|
+
fparent: group,
|
773
|
+
attr: {
|
774
|
+
x: this.coords2[i][j][0] - halfTickmarkSize,
|
775
|
+
y: this.coords2[i][j][1] - halfTickmarkSize,
|
776
|
+
width: prop.tickmarksSize,
|
777
|
+
height: prop.tickmarksSize,
|
778
|
+
fill: prop.tickmarks === 'filledrect' ? prop.colors[i] : fill,
|
779
|
+
stroke: prop.colors[i],
|
780
|
+
'stroke-width': prop.tickmarksLinewidth
|
781
|
+
}
|
782
|
+
});
|
783
|
+
|
784
|
+
s.setAttribute('data-dataset', i);
|
785
|
+
s.setAttribute('data-index', j);
|
786
|
+
}
|
787
|
+
}
|
788
|
+
}
|
789
|
+
};
|
790
|
+
|
791
|
+
|
792
|
+
|
793
|
+
|
794
|
+
|
795
|
+
|
796
|
+
|
797
|
+
|
798
|
+
//
|
799
|
+
// Draw the labels
|
800
|
+
//
|
801
|
+
this.drawLabels = function ()
|
802
|
+
{
|
803
|
+
var angles = this.angles2,
|
804
|
+
prop = this.properties,
|
805
|
+
labels = prop.labels;
|
806
|
+
|
807
|
+
for (var i=0,len=labels.length; i<len; ++i) {
|
808
|
+
|
809
|
+
if (!labels[i]) {
|
810
|
+
continue;
|
811
|
+
}
|
812
|
+
|
813
|
+
var endpoint = RG.SVG.TRIG.getRadiusEndPoint({
|
814
|
+
angle: RG.SVG.TRIG.TWOPI / labels.length * i - RG.SVG.TRIG.HALFPI,
|
815
|
+
r: this.radius + 15
|
816
|
+
});
|
817
|
+
|
818
|
+
var x = endpoint[0] + this.centerx,
|
819
|
+
y = endpoint[1] + this.centery;
|
820
|
+
|
821
|
+
//
|
822
|
+
// Horizontal alignment
|
823
|
+
|
824
|
+
if ((i / len) < 0.5) {
|
825
|
+
halign = 'left';
|
826
|
+
} else {
|
827
|
+
halign = 'right';
|
828
|
+
}
|
829
|
+
|
830
|
+
//
|
831
|
+
// Vertical alignment
|
832
|
+
//
|
833
|
+
if ((i / len) < 0.25 || (i / len) > 0.75) {
|
834
|
+
valign = 'bottom';
|
835
|
+
} else {
|
836
|
+
valign = 'top';
|
837
|
+
}
|
838
|
+
|
839
|
+
// Specify the alignment for labels which are on the axes
|
840
|
+
if ( (i / len) === 0 ) {halign = 'center';}
|
841
|
+
if ( (i / len) === 0.25 ) {valign = 'center';}
|
842
|
+
if ( (i / len) === 0.5 ) {halign = 'center';}
|
843
|
+
if ( (i / len) === 0.75 ) {valign = 'center';}
|
844
|
+
|
845
|
+
|
846
|
+
RG.SVG.text({
|
847
|
+
object: this,
|
848
|
+
svg: this.svg,
|
849
|
+
text: labels[i],
|
850
|
+
size: typeof prop.labelsSize === 'number' ? prop.labelsSize : prop.textSize,
|
851
|
+
x: x,
|
852
|
+
y: y,
|
853
|
+
halign: halign,
|
854
|
+
valign: 'center',
|
855
|
+
color: prop.labelsColor || prop.textColor,
|
856
|
+
bold: typeof prop.labelsBold === 'boolean' ? prop.labelsBold : prop.textBold,
|
857
|
+
italic: typeof prop.labelsItalic === 'boolean' ? prop.labelsItalic : prop.textItalic,
|
858
|
+
font: prop.labelsFont || prop.textFont
|
859
|
+
});
|
860
|
+
}
|
861
|
+
|
862
|
+
|
863
|
+
|
864
|
+
|
865
|
+
|
866
|
+
|
867
|
+
|
868
|
+
|
869
|
+
|
870
|
+
|
871
|
+
|
872
|
+
|
873
|
+
// Draw the scale if required
|
874
|
+
if (prop.scaleVisible) {
|
875
|
+
for (var i=0; i<this.scale.labels.length; ++i) {
|
876
|
+
|
877
|
+
var x = this.centerx;
|
878
|
+
var y = this.centery - (this.radius / this.scale.labels.length * (i+1) );
|
879
|
+
|
880
|
+
|
881
|
+
RG.SVG.text({
|
882
|
+
object: this,
|
883
|
+
svg: this.svg,
|
884
|
+
text: this.scale.labels[i],
|
885
|
+
size: prop.scaleSize || prop.textSize - 2,
|
886
|
+
x: x,
|
887
|
+
y: y,
|
888
|
+
halign: 'center',
|
889
|
+
valign: 'center',
|
890
|
+
background: 'rgba(255,255,255,0.7)',
|
891
|
+
padding:2,
|
892
|
+
color: prop.scaleColor || prop.textColor,
|
893
|
+
bold: typeof prop.scaleBold === 'boolean' ? prop.scaleBold : prop.textBold,
|
894
|
+
italic: typeof prop.scaleItalic === 'boolean' ? prop.scaleItalic : prop.textItalic,
|
895
|
+
font: prop.scaleFont || prop.textFont
|
896
|
+
});
|
897
|
+
}
|
898
|
+
|
899
|
+
// Draw the zero label
|
900
|
+
var str = RG.SVG.numberFormat({
|
901
|
+
object: this,
|
902
|
+
num: this.scale.min.toFixed(prop.scaleDecimals),
|
903
|
+
prepend: prop.scaleUnitsPre,
|
904
|
+
append: prop.scaleUnitsPost,
|
905
|
+
point: prop.scalePoint,
|
906
|
+
thousand: prop.scaleThousand,
|
907
|
+
formatter: prop.scaleFormatter
|
908
|
+
});
|
909
|
+
|
910
|
+
|
911
|
+
RG.SVG.text({
|
912
|
+
object: this,
|
913
|
+
svg: this.svg,
|
914
|
+
text: str,
|
915
|
+
size: prop.scaleSize || prop.textSize - 2,
|
916
|
+
x: this.centerx,
|
917
|
+
y: this.centery,
|
918
|
+
halign: 'center',
|
919
|
+
valign: 'center',
|
920
|
+
background: 'rgba(255,255,255,0.7)',
|
921
|
+
padding:2,
|
922
|
+
color: prop.scaleColor || prop.textColor,
|
923
|
+
bold: typeof prop.scaleBold === 'boolean' ? prop.scaleBold : prop.textBold,
|
924
|
+
italic: typeof prop.scaleItalic === 'boolean' ? prop.scaleItalic : prop.textItalic,
|
925
|
+
font: prop.scaleFont || prop.textFont
|
926
|
+
});
|
927
|
+
}
|
928
|
+
};
|
929
|
+
|
930
|
+
|
931
|
+
|
932
|
+
|
933
|
+
|
934
|
+
|
935
|
+
|
936
|
+
|
937
|
+
/**
|
938
|
+
* This function can be used to highlight a segment on the chart
|
939
|
+
*
|
940
|
+
* @param object segment The segment to highlight
|
941
|
+
*/
|
942
|
+
this.highlight = function (circle)
|
943
|
+
{
|
944
|
+
if (typeof prop.tickmarks === 'string' && prop.tickmarks) {
|
945
|
+
|
946
|
+
circle.setAttribute('fill', prop.highlightFill);
|
947
|
+
circle.setAttribute('stroke', prop.highlightStroke);
|
948
|
+
circle.setAttribute('stroke-width', prop.highlightLinewidth);
|
949
|
+
|
950
|
+
window.addEventListener ('mousedown', function (e)
|
951
|
+
{
|
952
|
+
circle.setAttribute('fill', 'transparent');
|
953
|
+
circle.setAttribute('stroke', 'transparent');
|
954
|
+
circle.setAttribute('stroke-width', 0);
|
955
|
+
|
956
|
+
RG.SVG.REG.set('highlight', this);
|
957
|
+
}, false);
|
958
|
+
|
959
|
+
this.highlight_hotspot = circle;
|
960
|
+
}
|
961
|
+
};
|
962
|
+
|
963
|
+
|
964
|
+
|
965
|
+
|
966
|
+
|
967
|
+
|
968
|
+
|
969
|
+
|
970
|
+
// Add the hide function
|
971
|
+
this.hideHighlight = function ()
|
972
|
+
{
|
973
|
+
if (this.highlight_hotspot) {
|
974
|
+
this.highlight_hotspot.setAttribute('fill', 'transparent');
|
975
|
+
this.highlight_hotspot.setAttribute('stroke', 'transparent');
|
976
|
+
this.highlight_hotspot.setAttribute('stroke-width', 0);
|
977
|
+
|
978
|
+
this.highlight_hotspot = null
|
979
|
+
}
|
980
|
+
};
|
981
|
+
|
982
|
+
|
983
|
+
|
984
|
+
|
985
|
+
|
986
|
+
|
987
|
+
|
988
|
+
|
989
|
+
/**
|
990
|
+
* This allows for easy specification of gradients
|
991
|
+
*/
|
992
|
+
this.parseColors = function ()
|
993
|
+
{
|
994
|
+
// Save the original colors so that they can be restored when the canvas is reset
|
995
|
+
if (!Object.keys(this.originalColors).length) {
|
996
|
+
this.originalColors = {
|
997
|
+
colors: RG.SVG.arrayClone(prop.colors),
|
998
|
+
highlightFill: RG.SVG.arrayClone(prop.highlightFill)
|
999
|
+
}
|
1000
|
+
}
|
1001
|
+
|
1002
|
+
|
1003
|
+
// colors
|
1004
|
+
var colors = prop.colors;
|
1005
|
+
|
1006
|
+
if (colors) {
|
1007
|
+
for (var i=0; i<colors.length; ++i) {
|
1008
|
+
colors[i] = RG.SVG.parseColorRadial({
|
1009
|
+
object: this,
|
1010
|
+
color: colors[i]
|
1011
|
+
});
|
1012
|
+
}
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
// Highlight fill
|
1016
|
+
prop.highlightFill = RG.SVG.parseColorRadial({
|
1017
|
+
object: this,
|
1018
|
+
color: prop.highlightFill
|
1019
|
+
});
|
1020
|
+
};
|
1021
|
+
|
1022
|
+
|
1023
|
+
|
1024
|
+
|
1025
|
+
|
1026
|
+
|
1027
|
+
|
1028
|
+
|
1029
|
+
//
|
1030
|
+
// Get the maximum value
|
1031
|
+
//
|
1032
|
+
this.getMaxValue = function ()
|
1033
|
+
{
|
1034
|
+
var max = 0;
|
1035
|
+
|
1036
|
+
if (prop.filled && prop.filledAccumulative) {
|
1037
|
+
this.max = RG.SVG.arrayMax(this.data[this.data.length - 1]);
|
1038
|
+
} else {
|
1039
|
+
for (var dataset=0,max=0; dataset<this.data.length; ++dataset) {
|
1040
|
+
this.max = ma.max(this.max, RG.SVG.arrayMax(this.data[dataset]));
|
1041
|
+
}
|
1042
|
+
}
|
1043
|
+
};
|
1044
|
+
|
1045
|
+
|
1046
|
+
|
1047
|
+
|
1048
|
+
|
1049
|
+
|
1050
|
+
|
1051
|
+
|
1052
|
+
//
|
1053
|
+
// Gets the radius of a value
|
1054
|
+
//
|
1055
|
+
//@param number The value to get the radius for
|
1056
|
+
//
|
1057
|
+
this.getRadius = function (value)
|
1058
|
+
{
|
1059
|
+
return ( (value - prop.scaleMin) / (this.scale.max - prop.scaleMin) ) * this.radius;
|
1060
|
+
};
|
1061
|
+
|
1062
|
+
|
1063
|
+
|
1064
|
+
|
1065
|
+
|
1066
|
+
|
1067
|
+
|
1068
|
+
|
1069
|
+
//
|
1070
|
+
// Adds the circular hotspot that facilitate tooltips
|
1071
|
+
// (to a single point)
|
1072
|
+
//
|
1073
|
+
this.addTooltipHotspots = function ()
|
1074
|
+
{
|
1075
|
+
if (prop.tooltips && prop.tooltips.length > 0) {
|
1076
|
+
|
1077
|
+
// Make the tooltipsEvent default to click
|
1078
|
+
if (prop.tooltipsEvent !== 'mousemove') {
|
1079
|
+
prop.tooltipsEvent = 'click';
|
1080
|
+
}
|
1081
|
+
|
1082
|
+
var group = RG.SVG.create({
|
1083
|
+
svg: this.svg,
|
1084
|
+
type: 'g',
|
1085
|
+
attr: {
|
1086
|
+
className: 'rgraph-radar-tooltip-hotspots'
|
1087
|
+
}
|
1088
|
+
});
|
1089
|
+
|
1090
|
+
for (var dataset=0,seq=0; dataset<this.coords2.length; ++dataset) {
|
1091
|
+
for (var i=0; i<this.coords2[dataset].length; ++i) {
|
1092
|
+
|
1093
|
+
var circle = RG.SVG.create({
|
1094
|
+
svg: this.svg,
|
1095
|
+
type: 'circle',
|
1096
|
+
parent: group,
|
1097
|
+
attr: {
|
1098
|
+
cx: this.coords2[dataset][i][0],
|
1099
|
+
cy: this.coords2[dataset][i][1],
|
1100
|
+
r: prop.tickmarksSize,
|
1101
|
+
fill: 'transparent',
|
1102
|
+
stroke: 'transparent',
|
1103
|
+
'stroke-width': 0
|
1104
|
+
},
|
1105
|
+
style: {
|
1106
|
+
cursor: 'pointer'
|
1107
|
+
}
|
1108
|
+
});
|
1109
|
+
|
1110
|
+
(function (dataset, index, seq, obj)
|
1111
|
+
{
|
1112
|
+
circle.addEventListener(prop.tooltipsEvent, function (e)
|
1113
|
+
{
|
1114
|
+
var tooltip = RG.SVG.REG.get('tooltip');
|
1115
|
+
|
1116
|
+
if (tooltip && tooltip.__sequentialIndex__ === seq) {
|
1117
|
+
return;
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
RG.SVG.hideTooltip();
|
1121
|
+
obj.hideHighlight();
|
1122
|
+
|
1123
|
+
// Show the tooltip
|
1124
|
+
RG.SVG.tooltip({
|
1125
|
+
object: obj,
|
1126
|
+
dataset: dataset,
|
1127
|
+
index: index,
|
1128
|
+
sequentialIndex: seq,
|
1129
|
+
text: prop.tooltips[seq],
|
1130
|
+
event: e
|
1131
|
+
});
|
1132
|
+
|
1133
|
+
// Highlight the rect that has been clicked on
|
1134
|
+
obj.highlight(this);
|
1135
|
+
|
1136
|
+
if (prop.tooltipsEvent === 'mousemove') {
|
1137
|
+
highlight.style.cursor = 'pointer';
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
}, false);
|
1141
|
+
|
1142
|
+
// Install the event listener that changes the
|
1143
|
+
// cursor if necessary
|
1144
|
+
if (prop.tooltipsEvent === 'click') {
|
1145
|
+
circle.addEventListener('mousemove', function (e)
|
1146
|
+
{
|
1147
|
+
e.target.style.cursor = 'pointer';
|
1148
|
+
}, false);
|
1149
|
+
}
|
1150
|
+
|
1151
|
+
}(dataset, i, seq++, this));
|
1152
|
+
}
|
1153
|
+
}
|
1154
|
+
}
|
1155
|
+
};
|
1156
|
+
|
1157
|
+
|
1158
|
+
|
1159
|
+
|
1160
|
+
|
1161
|
+
|
1162
|
+
|
1163
|
+
|
1164
|
+
//
|
1165
|
+
// A roundRobin effect for the Pie chart
|
1166
|
+
//
|
1167
|
+
// @param object Options for the effect
|
1168
|
+
// @param function An optional callback function to call when
|
1169
|
+
// the effect is complete
|
1170
|
+
//
|
1171
|
+
this.roundRobin = function ()
|
1172
|
+
{
|
1173
|
+
/*
|
1174
|
+
var obj = this,
|
1175
|
+
opt = arguments[0] || {},
|
1176
|
+
data = RG.SVG.arrayClone(this.data),
|
1177
|
+
prop = this.properties,
|
1178
|
+
frame = 1,
|
1179
|
+
frames = opt.frames || 30,
|
1180
|
+
callback = typeof opt.callback === 'function' ? opt.callback : function () {},
|
1181
|
+
dataSum = RG.SVG.arraySum(this.data),
|
1182
|
+
textColor = prop.textColor;
|
1183
|
+
|
1184
|
+
// Set the text color to transparent
|
1185
|
+
this.properties.textColor = 'rgba(0,0,0,0)';
|
1186
|
+
|
1187
|
+
|
1188
|
+
// Draw the chart first
|
1189
|
+
obj.draw();
|
1190
|
+
|
1191
|
+
// Now get the resulting angles
|
1192
|
+
angles = RG.SVG.arrayClone(obj.angles);
|
1193
|
+
|
1194
|
+
|
1195
|
+
function iterator ()
|
1196
|
+
{
|
1197
|
+
prop.roundRobinMultiplier = 1 / frames * frame++;
|
1198
|
+
|
1199
|
+
for (var i=0; i<obj.angles.length; ++i) {
|
1200
|
+
|
1201
|
+
var value = obj.data[i];
|
1202
|
+
|
1203
|
+
|
1204
|
+
|
1205
|
+
// NB This was an absolute git to work out for some reason.
|
1206
|
+
|
1207
|
+
|
1208
|
+
|
1209
|
+
obj.angles[i].start = angles[i].start * prop.roundRobinMultiplier;
|
1210
|
+
obj.angles[i].end = angles[i].end * prop.roundRobinMultiplier;
|
1211
|
+
|
1212
|
+
//var segment = (((value * prop.roundRobinMultiplier) / dataSum) * RG.SVG.TRIG.TWOPI);
|
1213
|
+
var segment = ((obj.angles[i].end - obj.angles[i].start) / 2);
|
1214
|
+
var explodedX = ma.cos(obj.angles[i].start + segment - RG.SVG.TRIG.HALFPI) * (prop.exploded[i] || 0);
|
1215
|
+
var explodedY = ma.sin(obj.angles[i].start + segment - RG.SVG.TRIG.HALFPI) * (prop.exploded[i] || 0);
|
1216
|
+
|
1217
|
+
|
1218
|
+
|
1219
|
+
var path = RG.SVG.TRIG.getArcPath({
|
1220
|
+
cx: obj.centerx + explodedX,
|
1221
|
+
cy: obj.centery + explodedY,
|
1222
|
+
r: obj.radius,// * prop.roundRobinMultiplier,
|
1223
|
+
start: obj.angles[i].start,
|
1224
|
+
end: obj.angles[i].end
|
1225
|
+
});
|
1226
|
+
|
1227
|
+
path = path + " L {1} {2} Z".format(
|
1228
|
+
obj.centerx + explodedX,
|
1229
|
+
obj.centery + explodedY
|
1230
|
+
);
|
1231
|
+
|
1232
|
+
if (obj.shadowNodes && obj.shadowNodes[i]) {
|
1233
|
+
obj.shadowNodes[i].setAttribute('d', path);
|
1234
|
+
}
|
1235
|
+
obj.nodes[i].setAttribute('d', path);
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
|
1239
|
+
if (frame <= frames) {
|
1240
|
+
RG.SVG.FX.update(iterator);
|
1241
|
+
} else {
|
1242
|
+
prop.textColor = textColor;
|
1243
|
+
|
1244
|
+
RG.SVG.redraw(obj.svg);
|
1245
|
+
|
1246
|
+
callback(obj);
|
1247
|
+
}
|
1248
|
+
}
|
1249
|
+
|
1250
|
+
iterator();
|
1251
|
+
|
1252
|
+
return this;
|
1253
|
+
*/
|
1254
|
+
};
|
1255
|
+
|
1256
|
+
|
1257
|
+
|
1258
|
+
|
1259
|
+
|
1260
|
+
|
1261
|
+
|
1262
|
+
|
1263
|
+
/**
|
1264
|
+
* Using a function to add events makes it easier to facilitate method
|
1265
|
+
* chaining
|
1266
|
+
*
|
1267
|
+
* @param string type The type of even to add
|
1268
|
+
* @param function func
|
1269
|
+
*/
|
1270
|
+
this.on = function (type, func)
|
1271
|
+
{
|
1272
|
+
if (type.substr(0,2) !== 'on') {
|
1273
|
+
type = 'on' + type;
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
RG.SVG.addCustomEventListener(this, type, func);
|
1277
|
+
|
1278
|
+
return this;
|
1279
|
+
};
|
1280
|
+
|
1281
|
+
|
1282
|
+
|
1283
|
+
|
1284
|
+
|
1285
|
+
|
1286
|
+
|
1287
|
+
|
1288
|
+
//
|
1289
|
+
// Used in chaining. Runs a function there and then - not waiting for
|
1290
|
+
// the events to fire (eg the onbeforedraw event)
|
1291
|
+
//
|
1292
|
+
// @param function func The function to execute
|
1293
|
+
//
|
1294
|
+
this.exec = function (func)
|
1295
|
+
{
|
1296
|
+
func(this);
|
1297
|
+
|
1298
|
+
return this;
|
1299
|
+
};
|
1300
|
+
|
1301
|
+
|
1302
|
+
|
1303
|
+
|
1304
|
+
|
1305
|
+
|
1306
|
+
|
1307
|
+
|
1308
|
+
//
|
1309
|
+
// Set the options that the user has provided
|
1310
|
+
//
|
1311
|
+
for (i in conf.options) {
|
1312
|
+
if (typeof i === 'string') {
|
1313
|
+
this.set(i, conf.options[i]);
|
1314
|
+
}
|
1315
|
+
}
|
1316
|
+
};
|
1317
|
+
|
1318
|
+
|
1319
|
+
|
1320
|
+
return this;
|
1321
|
+
|
1322
|
+
|
1323
|
+
|
1324
|
+
|
1325
|
+
// End module pattern
|
1326
|
+
})(window, document);
|