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
@@ -1,75 +1,1281 @@
|
|
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
|
+
*/
|
1
12
|
|
2
|
-
RGraph=window.RGraph||{isRGraph:true};
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
13
|
+
RGraph = window.RGraph || {isRGraph: true};
|
14
|
+
|
15
|
+
/**
|
16
|
+
* The bar chart constructor
|
17
|
+
*
|
18
|
+
* @param string canvas The canvas ID
|
19
|
+
* @param min integer The minimum value
|
20
|
+
* @param max integer The maximum value
|
21
|
+
* @param value integer The indicated value
|
22
|
+
*/
|
23
|
+
RGraph.Meter = function (conf)
|
24
|
+
{
|
25
|
+
/**
|
26
|
+
* Allow for object config style
|
27
|
+
*/
|
28
|
+
if ( typeof conf === 'object'
|
29
|
+
&& typeof conf.value !== 'undefined'
|
30
|
+
&& typeof conf.id === 'string') {
|
31
|
+
|
32
|
+
var id = conf.id
|
33
|
+
var canvas = document.getElementById(id);
|
34
|
+
var min = conf.min;
|
35
|
+
var max = conf.max;
|
36
|
+
var value = conf.value;
|
37
|
+
var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor)
|
38
|
+
|
39
|
+
} else {
|
40
|
+
|
41
|
+
var id = conf;
|
42
|
+
var canvas = document.getElementById(id);
|
43
|
+
var min = arguments[1];
|
44
|
+
var max = arguments[2];
|
45
|
+
var value = arguments[3];
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
// id, min, max, value
|
52
|
+
// Get the canvas and context objects
|
53
|
+
this.id = id;
|
54
|
+
this.canvas = canvas;
|
55
|
+
this.context = this.canvas.getContext ? this.canvas.getContext("2d", {alpha: (typeof id === 'object' && id.alpha === false) ? false : true}) : null;
|
56
|
+
this.canvas.__object__ = this;
|
57
|
+
this.type = 'meter';
|
58
|
+
this.min = RGraph.stringsToNumbers(min);
|
59
|
+
this.max = RGraph.stringsToNumbers(max);
|
60
|
+
this.value = RGraph.stringsToNumbers(value);
|
61
|
+
this.centerx = null;
|
62
|
+
this.centery = null;
|
63
|
+
this.radius = null;
|
64
|
+
this.isRGraph = true;
|
65
|
+
this.currentValue = null;
|
66
|
+
this.uid = RGraph.CreateUID();
|
67
|
+
this.canvas.uid = this.canvas.uid ? this.canvas.uid : RGraph.CreateUID();
|
68
|
+
this.colorsParsed = false;
|
69
|
+
this.coordsText = [];
|
70
|
+
this.original_colors = [];
|
71
|
+
this.firstDraw = true; // After the first draw this will be false
|
72
|
+
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Compatibility with older browsers
|
76
|
+
*/
|
77
|
+
//RGraph.OldBrowserCompat(this.context);
|
78
|
+
|
79
|
+
|
80
|
+
// Various config type stuff
|
81
|
+
this.properties =
|
82
|
+
{
|
83
|
+
'chart.background.image.url': null,
|
84
|
+
'chart.background.image.offsetx': 0,
|
85
|
+
'chart.background.image.offsety': 0,
|
86
|
+
'chart.background.image.stretch': true,
|
87
|
+
'chart.background.color': 'white',
|
88
|
+
'chart.gutter.left': 15,
|
89
|
+
'chart.gutter.right': 15,
|
90
|
+
'chart.gutter.top': 15,
|
91
|
+
'chart.gutter.bottom': 20,
|
92
|
+
'chart.linewidth': 1,
|
93
|
+
'chart.linewidth.segments': 0,
|
94
|
+
'chart.strokestyle': null,
|
95
|
+
'chart.border': true,
|
96
|
+
'chart.border.color': 'black',
|
97
|
+
'chart.text.font': 'Segoe UI, Arial, Verdana, sans-serif',
|
98
|
+
'chart.text.size': 12,
|
99
|
+
'chart.text.color': 'black',
|
100
|
+
'chart.text.valign': 'center',
|
101
|
+
'chart.text.accessible': false,
|
102
|
+
'chart.text.accessible.overflow': 'visible',
|
103
|
+
'chart.text.accessible.pointerevents': true,
|
104
|
+
'chart.value.text.decimals': 0,
|
105
|
+
'chart.value.text.units.pre': '',
|
106
|
+
'chart.value.text.units.post': '',
|
107
|
+
'chart.title': '',
|
108
|
+
'chart.title.background': null,
|
109
|
+
'chart.title.hpos': null,
|
110
|
+
'chart.title.vpos': null,
|
111
|
+
'chart.title.color': 'black',
|
112
|
+
'chart.title.bold': true,
|
113
|
+
'chart.title.font': null,
|
114
|
+
'chart.title.x': null,
|
115
|
+
'chart.title.y': null,
|
116
|
+
'chart.title.halign': null,
|
117
|
+
'chart.title.valign': null,
|
118
|
+
'chart.green.start': ((this.max - this.min) * 0.35) + this.min,
|
119
|
+
'chart.green.end': this.max,
|
120
|
+
'chart.green.color': '#207A20',
|
121
|
+
'chart.yellow.start': ((this.max - this.min) * 0.1) + this.min,
|
122
|
+
'chart.yellow.end': ((this.max - this.min) * 0.35) + this.min,
|
123
|
+
'chart.yellow.color': '#D0AC41',
|
124
|
+
'chart.red.start': this.min,
|
125
|
+
'chart.red.end': ((this.max - this.min) * 0.1) + this.min,
|
126
|
+
'chart.red.color': '#9E1E1E',
|
127
|
+
'chart.colors.ranges': null,
|
128
|
+
'chart.units.pre': '',
|
129
|
+
'chart.units.post': '',
|
130
|
+
'chart.contextmenu': null,
|
131
|
+
'chart.zoom.factor': 1.5,
|
132
|
+
'chart.zoom.fade.in': true,
|
133
|
+
'chart.zoom.fade.out': true,
|
134
|
+
'chart.zoom.hdir': 'right',
|
135
|
+
'chart.zoom.vdir': 'down',
|
136
|
+
'chart.zoom.frames': 25,
|
137
|
+
'chart.zoom.delay': 16.666,
|
138
|
+
'chart.zoom.shadow': true,
|
139
|
+
'chart.zoom.background': true,
|
140
|
+
'chart.zoom.action': 'zoom',
|
141
|
+
'chart.annotatable': false,
|
142
|
+
'chart.annotate.color': 'black',
|
143
|
+
'chart.shadow': false,
|
144
|
+
'chart.shadow.color': 'rgba(0,0,0,0.5)',
|
145
|
+
'chart.shadow.blur': 3,
|
146
|
+
'chart.shadow.offsetx': 3,
|
147
|
+
'chart.shadow.offsety': 3,
|
148
|
+
'chart.resizable': false,
|
149
|
+
'chart.resize.handle.adjust': [0,0],
|
150
|
+
'chart.resize.handle.background': null,
|
151
|
+
'chart.tickmarks.small.num': 100,
|
152
|
+
'chart.tickmarks.big.num': 10,
|
153
|
+
'chart.tickmarks.small.color': '#bbb',
|
154
|
+
'chart.tickmarks.big.color': 'black',
|
155
|
+
'chart.scale.decimals': 0,
|
156
|
+
'chart.scale.point': '.',
|
157
|
+
'chart.scale.thousand': ',',
|
158
|
+
'chart.radius': null,
|
159
|
+
'chart.centerx': null,
|
160
|
+
'chart.centery': null,
|
161
|
+
'chart.labels': true,
|
162
|
+
'chart.labels.count': 10,
|
163
|
+
'chart.labels.specific': null,
|
164
|
+
'chart.segment.radius.start': 0,
|
165
|
+
'chart.needle.radius': null,
|
166
|
+
'chart.needle.tail': false,
|
167
|
+
'chart.needle.head': true,
|
168
|
+
'chart.needle.color': 'black',
|
169
|
+
'chart.needle.image.url': null,
|
170
|
+
'chart.needle.image.offsetx': 0,
|
171
|
+
'chart.needle.image.offsety': 0,
|
172
|
+
'chart.adjustable': false,
|
173
|
+
'chart.angles.start': RGraph.PI,
|
174
|
+
'chart.angles.end': RGraph.TWOPI,
|
175
|
+
'chart.centerpin.stroke': 'black',
|
176
|
+
'chart.centerpin.fill': 'white',
|
177
|
+
'chart.clearto': 'rgba(0,0,0,0)'
|
178
|
+
}
|
179
|
+
|
180
|
+
|
181
|
+
// Check for support
|
182
|
+
if (!this.canvas) {
|
183
|
+
alert('[METER] No canvas support');
|
184
|
+
return;
|
185
|
+
}
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
/*
|
190
|
+
* Translate half a pixel for antialiasing purposes - but only if it hasn't beeen
|
191
|
+
* done already
|
192
|
+
*/
|
193
|
+
if (!this.canvas.__rgraph_aa_translated__) {
|
194
|
+
this.context.translate(0.5,0.5);
|
195
|
+
|
196
|
+
this.canvas.__rgraph_aa_translated__ = true;
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
// Short variable names
|
203
|
+
var RG = RGraph,
|
204
|
+
ca = this.canvas,
|
205
|
+
co = ca.getContext('2d'),
|
206
|
+
prop = this.properties,
|
207
|
+
pa2 = RG.path2,
|
208
|
+
win = window,
|
209
|
+
doc = document,
|
210
|
+
ma = Math
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
/**
|
215
|
+
* "Decorate" the object with the generic effects if the effects library has been included
|
216
|
+
*/
|
217
|
+
if (RG.Effects && typeof RG.Effects.decorate === 'function') {
|
218
|
+
RG.Effects.decorate(this);
|
219
|
+
}
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
/**
|
224
|
+
* A setter
|
225
|
+
*
|
226
|
+
* @param name string The name of the property to set
|
227
|
+
* @param value mixed The value of the property
|
228
|
+
*/
|
229
|
+
this.set =
|
230
|
+
this.Set = function (name)
|
231
|
+
{
|
232
|
+
var value = arguments[1] || null;
|
233
|
+
|
234
|
+
/**
|
235
|
+
* the number of arguments is only one and it's an
|
236
|
+
* object - parse it for configuration data and return.
|
237
|
+
*/
|
238
|
+
if (arguments.length === 1 && typeof name === 'object') {
|
239
|
+
RG.parseObjectStyleConfig(this, name);
|
240
|
+
return this;
|
241
|
+
}
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
|
247
|
+
/**
|
248
|
+
* This should be done first - prepend the propertyy name with "chart." if necessary
|
249
|
+
*/
|
250
|
+
if (name.substr(0,6) != 'chart.') {
|
251
|
+
name = 'chart.' + name;
|
252
|
+
}
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
// Convert uppercase letters to dot+lower case letter
|
258
|
+
while(name.match(/([A-Z])/)) {
|
259
|
+
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
260
|
+
}
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
if (name == 'chart.value') {
|
266
|
+
this.value = value;
|
267
|
+
return;
|
268
|
+
}
|
269
|
+
|
270
|
+
|
271
|
+
|
272
|
+
|
273
|
+
|
274
|
+
|
275
|
+
prop[name] = value;
|
276
|
+
|
277
|
+
return this;
|
278
|
+
};
|
279
|
+
|
280
|
+
|
281
|
+
|
282
|
+
|
283
|
+
/**
|
284
|
+
* A getter
|
285
|
+
*
|
286
|
+
* @param name string The name of the property to get
|
287
|
+
*/
|
288
|
+
this.get =
|
289
|
+
this.Get = function (name)
|
290
|
+
{
|
291
|
+
/**
|
292
|
+
* This should be done first - prepend the property name with "chart." if necessary
|
293
|
+
*/
|
294
|
+
if (name.substr(0,6) != 'chart.') {
|
295
|
+
name = 'chart.' + name;
|
296
|
+
}
|
297
|
+
|
298
|
+
// Convert uppercase letters to dot+lower case letter
|
299
|
+
while(name.match(/([A-Z])/)) {
|
300
|
+
name = name.replace(/([A-Z])/, '.' + RegExp.$1.toLowerCase());
|
301
|
+
}
|
302
|
+
|
303
|
+
if (name == 'chart.value') {
|
304
|
+
return this.value;
|
305
|
+
}
|
306
|
+
|
307
|
+
return prop[name];
|
308
|
+
};
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
/**
|
314
|
+
* The function you call to draw the bar chart
|
315
|
+
*/
|
316
|
+
this.draw =
|
317
|
+
this.Draw = function ()
|
318
|
+
{
|
319
|
+
/**
|
320
|
+
* Fire the onbeforedraw event
|
321
|
+
*/
|
322
|
+
RG.FireCustomEvent(this, 'onbeforedraw');
|
323
|
+
|
324
|
+
/**
|
325
|
+
* Constrain the value to be within the min and max
|
326
|
+
*/
|
327
|
+
if (this.value > this.max) this.value = this.max;
|
328
|
+
if (this.value < this.min) this.value = this.min;
|
329
|
+
|
330
|
+
/**
|
331
|
+
* Set the current value
|
332
|
+
*/
|
333
|
+
this.currentValue = this.value;
|
334
|
+
|
335
|
+
/**
|
336
|
+
* This is new in May 2011 and facilitates indiviual gutter settings,
|
337
|
+
* eg chart.gutter.left
|
338
|
+
*/
|
339
|
+
this.gutterLeft = prop['chart.gutter.left'];
|
340
|
+
this.gutterRight = prop['chart.gutter.right'];
|
341
|
+
this.gutterTop = prop['chart.gutter.top'];
|
342
|
+
this.gutterBottom = prop['chart.gutter.bottom'];
|
343
|
+
|
344
|
+
this.centerx = ((ca.width - this.gutterLeft - this.gutterRight) / 2) + this.gutterLeft;
|
345
|
+
this.centery = ca.height - this.gutterBottom;
|
346
|
+
this.radius = Math.min(
|
347
|
+
(ca.width - this.gutterLeft - this.gutterRight) / 2,
|
348
|
+
(ca.height - this.gutterTop - this.gutterBottom)
|
349
|
+
);
|
350
|
+
|
351
|
+
/**
|
352
|
+
* Stop this growing uncontrollably
|
353
|
+
*/
|
354
|
+
this.coordsText = [];
|
355
|
+
|
356
|
+
|
357
|
+
|
358
|
+
/**
|
359
|
+
* Custom centerx, centery and radius
|
360
|
+
*/
|
361
|
+
if (typeof(prop['chart.centerx']) == 'number') this.centerx = prop['chart.centerx'];
|
362
|
+
if (typeof(prop['chart.centery']) == 'number') this.centery = prop['chart.centery'];
|
363
|
+
if (typeof(prop['chart.radius']) == 'number') this.radius = prop['chart.radius'];
|
364
|
+
|
365
|
+
|
366
|
+
/**
|
367
|
+
* Parse the colors for gradients. Its down here so that the center X/Y can be used
|
368
|
+
*/
|
369
|
+
if (!this.colorsParsed) {
|
370
|
+
|
371
|
+
this.parseColors();
|
372
|
+
|
373
|
+
// Don't want to do this again
|
374
|
+
this.colorsParsed = true;
|
375
|
+
}
|
376
|
+
|
377
|
+
|
378
|
+
this.drawBackground();
|
379
|
+
this.drawLabels();
|
380
|
+
this.drawNeedle();
|
381
|
+
this.drawReadout();
|
382
|
+
|
383
|
+
/**
|
384
|
+
* Draw the title
|
385
|
+
*/
|
386
|
+
RG.DrawTitle(this, prop['chart.title'], this.gutterTop, null, prop['chart.title.size'] ? prop['chart.title.size'] : prop['chart.text.size'] + 2);
|
387
|
+
|
388
|
+
/**
|
389
|
+
* Setup the context menu if required
|
390
|
+
*/
|
391
|
+
if (prop['chart.contextmenu']) {
|
392
|
+
RG.ShowContext(this);
|
393
|
+
}
|
394
|
+
|
395
|
+
|
396
|
+
/**
|
397
|
+
* This function enables resizing
|
398
|
+
*/
|
399
|
+
if (prop['chart.resizable']) {
|
400
|
+
RG.AllowResizing(this);
|
401
|
+
}
|
402
|
+
|
403
|
+
|
404
|
+
/**
|
405
|
+
* This installs the event listeners
|
406
|
+
*/
|
407
|
+
RG.InstallEventListeners(this);
|
408
|
+
|
409
|
+
|
410
|
+
|
411
|
+
/**
|
412
|
+
* Fire the onfirstdraw event
|
413
|
+
*/
|
414
|
+
if (this.firstDraw) {
|
415
|
+
RG.fireCustomEvent(this, 'onfirstdraw');
|
416
|
+
this.firstDraw = false;
|
417
|
+
this.firstDrawFunc();
|
418
|
+
}
|
419
|
+
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
/**
|
424
|
+
* Fire the RGraph ondraw event
|
425
|
+
*/
|
426
|
+
RG.FireCustomEvent(this, 'ondraw');
|
427
|
+
|
428
|
+
|
429
|
+
|
430
|
+
return this;
|
431
|
+
};
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
/**
|
436
|
+
* Used in chaining. Runs a function there and then - not waiting for
|
437
|
+
* the events to fire (eg the onbeforedraw event)
|
438
|
+
*
|
439
|
+
* @param function func The function to execute
|
440
|
+
*/
|
441
|
+
this.exec = function (func)
|
442
|
+
{
|
443
|
+
func(this);
|
444
|
+
|
445
|
+
return this;
|
446
|
+
};
|
447
|
+
|
448
|
+
|
449
|
+
|
450
|
+
|
451
|
+
/**
|
452
|
+
* Draws the background of the chart
|
453
|
+
*/
|
454
|
+
this.drawBackground =
|
455
|
+
this.DrawBackground = function ()
|
456
|
+
{
|
457
|
+
/**
|
458
|
+
* First draw the background image if it's defined
|
459
|
+
*/
|
460
|
+
if (typeof prop['chart.background.image.url'] === 'string' && !this.__background_image__) {
|
461
|
+
|
462
|
+
var x = 0 + prop['chart.background.image.offsetx'];
|
463
|
+
var y = 0 + prop['chart.background.image.offsety'];
|
464
|
+
var img = new Image();
|
465
|
+
|
466
|
+
this.__background_image__ = img;
|
467
|
+
img.src = prop['chart.background.image.url'];
|
468
|
+
|
469
|
+
img.onload = function ()
|
470
|
+
{
|
471
|
+
if (prop['chart.background.image.stretch']) {
|
472
|
+
co.drawImage(this, x,y,ca.width, ca.height);
|
473
|
+
} else {
|
474
|
+
co.drawImage(this, x,y);
|
475
|
+
}
|
476
|
+
RG.redraw();
|
477
|
+
}
|
478
|
+
|
479
|
+
} else if (this.__background_image__) {
|
480
|
+
|
481
|
+
var x = 0 + prop['chart.background.image.offsetx'];
|
482
|
+
var y = 0 + prop['chart.background.image.offsety'];
|
483
|
+
|
484
|
+
if (prop['chart.background.image.stretch']) {
|
485
|
+
co.drawImage(this.__background_image__, x,y,ca.width, ca.height);
|
486
|
+
} else {
|
487
|
+
co.drawImage(this.__background_image__, x,y);
|
488
|
+
}
|
489
|
+
}
|
490
|
+
|
491
|
+
|
492
|
+
|
493
|
+
/**
|
494
|
+
* Draw the white background
|
495
|
+
*/
|
496
|
+
co.beginPath();
|
497
|
+
|
498
|
+
co.fillStyle = prop['chart.background.color'];
|
499
|
+
|
500
|
+
if (prop['chart.shadow']) {
|
501
|
+
RG.SetShadow(this, prop['chart.shadow.color'],prop['chart.shadow.offsetx'],prop['chart.shadow.offsety'], prop['chart.shadow.blur']);
|
502
|
+
}
|
503
|
+
co.moveTo(this.centerx,this.centery);
|
504
|
+
co.arc(this.centerx,
|
505
|
+
this.centery,
|
506
|
+
this.radius,
|
507
|
+
prop['chart.angles.start'],
|
508
|
+
prop['chart.angles.end'],
|
509
|
+
false);
|
510
|
+
|
511
|
+
co.fill();
|
512
|
+
|
513
|
+
RG.NoShadow(this);
|
514
|
+
|
515
|
+
|
516
|
+
// Draw the shadow
|
517
|
+
if (prop['chart.shadow']) {
|
518
|
+
|
519
|
+
co.beginPath();
|
520
|
+
var r = (this.radius * 0.06) > 40 ? 40 : (this.radius * 0.06);
|
521
|
+
co.arc(this.centerx, this.centery, r, 0, RG.TWOPI, 0);
|
522
|
+
co.fill();
|
523
|
+
|
524
|
+
RG.NoShadow(this);
|
525
|
+
}
|
526
|
+
|
527
|
+
|
528
|
+
|
529
|
+
// First, draw the grey tickmarks
|
530
|
+
if (prop['chart.tickmarks.small.num']) {
|
531
|
+
for (var i=0; i<(prop['chart.angles.end'] - prop['chart.angles.start']); i+=(RG.PI / prop['chart.tickmarks.small.num'])) {
|
532
|
+
co.beginPath();
|
533
|
+
co.strokeStyle = prop['chart.tickmarks.small.color'];
|
534
|
+
co.arc(this.centerx, this.centery, this.radius, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.00001, 0);
|
535
|
+
co.arc(this.centerx, this.centery, this.radius - 5, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.00001, 0);
|
536
|
+
co.stroke();
|
537
|
+
}
|
538
|
+
|
539
|
+
// Draw the semi-circle that makes the tickmarks
|
540
|
+
co.beginPath();
|
541
|
+
co.fillStyle = prop['chart.background.color'];
|
542
|
+
co.arc(this.centerx, this.centery, this.radius - 4, prop['chart.angles.start'], prop['chart.angles.end'], false);
|
543
|
+
co.closePath();
|
544
|
+
co.fill();
|
545
|
+
}
|
546
|
+
|
547
|
+
|
548
|
+
// Second, draw the darker tickmarks. First run draws them in white to get rid of the existing tickmark,
|
549
|
+
// then the second run draws them in the requested color
|
550
|
+
|
551
|
+
|
552
|
+
if (prop['chart.tickmarks.big.num']) {
|
553
|
+
var colors = ['white','white',prop['chart.tickmarks.big.color']];
|
554
|
+
for (var j=0; j<colors.length; ++j) {
|
555
|
+
for (var i=0; i<(prop['chart.angles.end'] - prop['chart.angles.start']); i+=((prop['chart.angles.end'] - prop['chart.angles.start']) / prop['chart.tickmarks.big.num'])) {
|
556
|
+
co.beginPath();
|
557
|
+
co.strokeStyle = colors[j];
|
558
|
+
co.arc(this.centerx, this.centery, this.radius, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.001, 0);
|
559
|
+
co.arc(this.centerx, this.centery, this.radius - 5, prop['chart.angles.start'] + i, prop['chart.angles.start'] + i + 0.0001, 0);
|
560
|
+
co.stroke();
|
561
|
+
}
|
562
|
+
}
|
563
|
+
}
|
564
|
+
|
565
|
+
// Draw the white circle that makes the tickmarks
|
566
|
+
co.beginPath();
|
567
|
+
co.fillStyle = prop['chart.background.color'];
|
568
|
+
co.moveTo(this.centerx, this.centery);
|
569
|
+
co.arc(this.centerx, this.centery, this.radius - 7, prop['chart.angles.start'], prop['chart.angles.end'], false);
|
570
|
+
co.closePath();
|
571
|
+
co.fill();
|
572
|
+
|
573
|
+
/**
|
574
|
+
* Color ranges - either green/yellow/red or an arbitrary number of ranges
|
575
|
+
*/
|
576
|
+
var ranges = prop['chart.colors.ranges'];
|
577
|
+
|
578
|
+
if (RG.is_array(prop['chart.colors.ranges'])) {
|
579
|
+
|
580
|
+
var ranges = prop['chart.colors.ranges'];
|
581
|
+
|
582
|
+
for (var i=0; i<ranges.length; ++i) {
|
583
|
+
|
584
|
+
co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : ranges[i][2];
|
585
|
+
co.fillStyle = ranges[i][2];
|
586
|
+
co.lineWidth = prop['chart.linewidth.segments'];
|
587
|
+
|
588
|
+
co.beginPath();
|
589
|
+
co.arc(this.centerx,
|
590
|
+
this.centery,
|
591
|
+
this.radius * 0.85,
|
592
|
+
(((ranges[i][0] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
593
|
+
(((ranges[i][1] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
594
|
+
false);
|
595
|
+
|
596
|
+
if (prop['chart.segment.radius.start'] > 0) {
|
597
|
+
co.arc(this.centerx,
|
598
|
+
this.centery,
|
599
|
+
prop['chart.segment.radius.start'],
|
600
|
+
(((ranges[i][1] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
601
|
+
(((ranges[i][0] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
602
|
+
true);
|
603
|
+
} else {
|
604
|
+
co.lineTo(this.centerx, this.centery);
|
605
|
+
}
|
606
|
+
|
607
|
+
co.closePath();
|
608
|
+
co.stroke();
|
609
|
+
co.fill();
|
610
|
+
}
|
611
|
+
|
612
|
+
// Stops the last line from being changed to a big linewidth.
|
613
|
+
co.beginPath();
|
614
|
+
|
615
|
+
} else {
|
616
|
+
co.lineWidth = prop['chart.linewidth'];
|
617
|
+
|
618
|
+
// Draw the green area
|
619
|
+
co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : prop['chart.green.color'];
|
620
|
+
co.fillStyle = prop['chart.green.color'];
|
621
|
+
co.lineWidth = prop['chart.linewidth.segments'];
|
622
|
+
|
623
|
+
co.beginPath();
|
624
|
+
co.arc(this.centerx,
|
625
|
+
this.centery,
|
626
|
+
this.radius * 0.85,
|
627
|
+
(((prop['chart.green.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - this.properties['chart.angles.start'])) + prop['chart.angles.start'],
|
628
|
+
(((prop['chart.green.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
629
|
+
false);
|
630
|
+
|
631
|
+
if (prop['chart.segment.radius.start'] > 0) {
|
632
|
+
|
633
|
+
co.arc(this.centerx,
|
634
|
+
this.centery,
|
635
|
+
prop['chart.segment.radius.start'],
|
636
|
+
(((prop['chart.green.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
637
|
+
(((prop['chart.green.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
638
|
+
true);
|
639
|
+
} else {
|
640
|
+
co.lineTo(this.centerx, this.centery);
|
641
|
+
}
|
642
|
+
|
643
|
+
co.closePath();
|
644
|
+
co.stroke();
|
645
|
+
co.fill();
|
646
|
+
|
647
|
+
// Draw the yellow area
|
648
|
+
co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : prop['chart.yellow.color'];
|
649
|
+
co.fillStyle = prop['chart.yellow.color'];
|
650
|
+
co.lineWidth = prop['chart.linewidth.segments'];
|
651
|
+
co.beginPath();
|
652
|
+
co.arc(this.centerx,
|
653
|
+
this.centery,
|
654
|
+
this.radius * 0.85,
|
655
|
+
(((prop['chart.yellow.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
656
|
+
(((prop['chart.yellow.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
657
|
+
false);
|
658
|
+
|
659
|
+
if (prop['chart.segment.radius.start'] > 0) {
|
660
|
+
co.arc(this.centerx,
|
661
|
+
this.centery,
|
662
|
+
prop['chart.segment.radius.start'],
|
663
|
+
(((prop['chart.yellow.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
664
|
+
(((prop['chart.yellow.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
665
|
+
true);
|
666
|
+
} else {
|
667
|
+
co.lineTo(this.centerx, this.centery);
|
668
|
+
}
|
669
|
+
|
670
|
+
co.closePath();
|
671
|
+
co.stroke();
|
672
|
+
co.fill();
|
673
|
+
|
674
|
+
// Draw the red area
|
675
|
+
co.strokeStyle = prop['chart.strokestyle'] ? prop['chart.strokestyle'] : prop['chart.red.color'];
|
676
|
+
co.fillStyle = prop['chart.red.color'];
|
677
|
+
co.lineWidth = prop['chart.linewidth.segments'];
|
678
|
+
|
679
|
+
co.beginPath();
|
680
|
+
co.arc(this.centerx,
|
681
|
+
this.centery,this.radius * 0.85,
|
682
|
+
(((prop['chart.red.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
683
|
+
(((prop['chart.red.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
684
|
+
false);
|
685
|
+
|
686
|
+
if (prop['chart.segment.radius.start'] > 0) {
|
687
|
+
co.arc(this.centerx,
|
688
|
+
this.centery,
|
689
|
+
prop['chart.segment.radius.start'],
|
690
|
+
(((prop['chart.red.end'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
691
|
+
(((prop['chart.red.start'] - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'],
|
692
|
+
true);
|
693
|
+
} else {
|
694
|
+
co.lineTo(this.centerx, this.centery);
|
695
|
+
}
|
696
|
+
|
697
|
+
co.closePath();
|
698
|
+
co.stroke();
|
699
|
+
co.fill();
|
700
|
+
|
701
|
+
// Revert the linewidth
|
702
|
+
co.lineWidth = 1;
|
703
|
+
}
|
704
|
+
|
705
|
+
// Draw the outline
|
706
|
+
if (prop['chart.border']) {
|
707
|
+
co.strokeStyle = prop['chart.border.color'];
|
708
|
+
co.lineWidth = prop['chart.linewidth'];
|
709
|
+
|
710
|
+
co.beginPath();
|
711
|
+
co.moveTo(this.centerx, this.centery);
|
712
|
+
co.arc(this.centerx,
|
713
|
+
this.centery,
|
714
|
+
this.radius,
|
715
|
+
prop['chart.angles.start'],
|
716
|
+
prop['chart.angles.end'],
|
717
|
+
false);
|
718
|
+
co.closePath();
|
719
|
+
}
|
720
|
+
|
721
|
+
co.stroke();
|
722
|
+
|
723
|
+
// Reset the linewidth back to 1
|
724
|
+
co.lineWidth = 1;
|
725
|
+
};
|
726
|
+
|
727
|
+
|
728
|
+
|
729
|
+
|
730
|
+
/**
|
731
|
+
* Draws the pointer
|
732
|
+
*/
|
733
|
+
this.drawNeedle =
|
734
|
+
this.DrawNeedle = function ()
|
735
|
+
{
|
736
|
+
/**
|
737
|
+
* The angle that the needle is at
|
738
|
+
*/
|
739
|
+
var a = (((this.value - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'];
|
740
|
+
|
741
|
+
/**
|
742
|
+
* First draw the background image if it's defined
|
743
|
+
*/
|
744
|
+
if (typeof prop['chart.needle.image.url'] === 'string' && !this.__needle_image__) {
|
745
|
+
|
746
|
+
var img = new Image();
|
747
|
+
|
748
|
+
this.__needle_image__ = img;
|
749
|
+
img.src = prop['chart.needle.image.url'];
|
750
|
+
|
751
|
+
img.onload = function ()
|
752
|
+
{
|
753
|
+
co.save();
|
754
|
+
RG.rotateCanvas(ca, this.centerx, this.centery, a);
|
755
|
+
co.drawImage(this,
|
756
|
+
this.centerx + prop['chart.needle.image.offsetx'],
|
757
|
+
this.centery + prop['chart.needle.image.offsety']);
|
758
|
+
co.restore();
|
759
|
+
|
760
|
+
RG.redraw();
|
761
|
+
}
|
762
|
+
|
763
|
+
} else if (this.__needle_image__) {
|
764
|
+
|
765
|
+
co.save();
|
766
|
+
RG.rotateCanvas(ca, this.centerx, this.centery, a);
|
767
|
+
co.drawImage(this.__needle_image__,
|
768
|
+
this.centerx + prop['chart.needle.image.offsetx'],
|
769
|
+
this.centery + prop['chart.needle.image.offsety']);
|
770
|
+
co.restore();
|
771
|
+
}
|
772
|
+
|
773
|
+
|
774
|
+
|
775
|
+
|
776
|
+
|
777
|
+
|
778
|
+
|
779
|
+
|
780
|
+
// Allow customising the needle radius
|
781
|
+
var needleRadius = typeof(prop['chart.needle.radius']) == 'number' ? prop['chart.needle.radius'] : this.radius * 0.7;
|
782
|
+
|
783
|
+
// First draw the circle at the bottom
|
784
|
+
co.fillStyle = 'black';
|
785
|
+
co.lineWidth = this.radius >= 200 ? 7 : 3;
|
786
|
+
co.lineCap = 'round';
|
787
|
+
|
788
|
+
// Now, draw the arm of the needle
|
789
|
+
co.beginPath();
|
790
|
+
co.strokeStyle = prop['chart.needle.color'];
|
791
|
+
if (typeof(prop['chart.needle.linewidth']) == 'number') co.lineWidth = prop['chart.needle.linewidth'];
|
792
|
+
|
793
|
+
|
794
|
+
co.arc(this.centerx, this.centery, needleRadius, a, a + 0.001, false);
|
795
|
+
co.lineTo(this.centerx, this.centery);
|
796
|
+
co.stroke();
|
797
|
+
|
798
|
+
// Draw the triangular needle head
|
799
|
+
if (prop['chart.needle.head']) {
|
800
|
+
|
801
|
+
co.fillStyle = prop['chart.needle.color'];
|
802
|
+
co.beginPath();
|
803
|
+
co.lineWidth = 1;
|
804
|
+
//co.moveTo(this.centerx, this.centery);
|
805
|
+
co.arc(this.centerx, this.centery, needleRadius + 15, a, a + 0.001, 0);
|
806
|
+
co.arc(this.centerx, this.centery, needleRadius - 15, a + 0.087, a + 0.087999, 0);
|
807
|
+
co.arc(this.centerx, this.centery, needleRadius - 15, a - 0.087, a - 0.087999, 1);
|
808
|
+
co.fill();
|
809
|
+
}
|
810
|
+
|
811
|
+
// Draw the tail if requested
|
812
|
+
if (prop['chart.needle.tail']) {
|
813
|
+
co.beginPath();
|
814
|
+
co.strokeStyle = prop['chart.needle.color'];
|
815
|
+
if (typeof(prop['chart.needle.linewidth']) == 'number') co.lineWidth = prop['chart.needle.linewidth'];
|
816
|
+
|
817
|
+
var a = ((this.value - this.min) / (this.max - this.min) * (this.properties['chart.angles.end'] - this.properties['chart.angles.start'])) + this.properties['chart.angles.start'] + RG.PI;
|
818
|
+
co.arc(this.centerx, this.centery, 25, a, a + 0.001, false);
|
819
|
+
co.lineTo(this.centerx, this.centery);
|
820
|
+
co.stroke();
|
821
|
+
}
|
822
|
+
|
823
|
+
// Draw the center circle (the stroke)
|
824
|
+
var r = (this.radius * 0.06) > 40 ? 40 : (this.radius * 0.06);
|
825
|
+
|
826
|
+
co.beginPath();
|
827
|
+
co.fillStyle = prop['chart.centerpin.stroke'];
|
828
|
+
co.arc(this.centerx, this.centery, r, 0 + 0.001, RG.TWOPI, 0);
|
829
|
+
co.fill();
|
830
|
+
|
831
|
+
|
832
|
+
|
833
|
+
|
834
|
+
|
835
|
+
|
836
|
+
|
837
|
+
|
838
|
+
|
839
|
+
|
840
|
+
|
841
|
+
|
842
|
+
|
843
|
+
|
844
|
+
// Draw the centre bit of the circle (the fill)
|
845
|
+
co.fillStyle = prop['chart.centerpin.fill'];
|
846
|
+
co.beginPath();
|
847
|
+
co.arc(this.centerx, this.centery, r - 2, 0 + 0.001, RG.TWOPI, 0);
|
848
|
+
co.fill();
|
849
|
+
};
|
850
|
+
|
851
|
+
|
852
|
+
|
853
|
+
|
854
|
+
/**
|
855
|
+
* Draws the labels
|
856
|
+
*/
|
857
|
+
this.drawLabels =
|
858
|
+
this.DrawLabels = function ()
|
859
|
+
{
|
860
|
+
if (!prop['chart.labels']) {
|
861
|
+
return;
|
862
|
+
}
|
863
|
+
|
864
|
+
var radius = this.radius,
|
865
|
+
text_size = prop['chart.text.size'],
|
866
|
+
text_font = prop['chart.text.font'],
|
867
|
+
units_post = prop['chart.units.post'],
|
868
|
+
units_pre = prop['chart.units.pre'],
|
869
|
+
centerx = this.centerx,
|
870
|
+
centery = this.centery,
|
871
|
+
min = this.min,
|
872
|
+
max = this.max,
|
873
|
+
decimals = prop['chart.scale.decimals'],
|
874
|
+
numLabels = prop['chart.labels.count'],
|
875
|
+
specific = prop['chart.labels.specific']
|
876
|
+
|
877
|
+
|
878
|
+
|
879
|
+
|
880
|
+
//
|
881
|
+
// Draw the specific labels if they're specifid
|
882
|
+
//
|
883
|
+
if (specific) {
|
884
|
+
for (var i=0; i<specific.length; ++i) {
|
885
|
+
|
886
|
+
var angle = this.getAngle(specific[i][1]),
|
887
|
+
angle_degrees = angle * (180 / RG.PI),
|
888
|
+
text = specific[i][0].toString(),
|
889
|
+
coords = RG.getRadiusEndPoint(this.centerx, this.centery, angle, this.radius * 0.925)
|
890
|
+
|
891
|
+
|
892
|
+
RG.text2(this, {
|
893
|
+
'font':text_font,
|
894
|
+
'size':text_size,
|
895
|
+
'x': coords[0],
|
896
|
+
'y': coords[1],
|
897
|
+
'text':text,
|
898
|
+
'halign':'center',
|
899
|
+
'valign':'center',
|
900
|
+
'angle':angle_degrees + 90,
|
901
|
+
'bounding': false,
|
902
|
+
'tag': 'labels-specific',
|
903
|
+
color: 'black'
|
904
|
+
});
|
905
|
+
}
|
906
|
+
|
907
|
+
return;
|
908
|
+
}
|
909
|
+
|
910
|
+
|
911
|
+
|
912
|
+
|
913
|
+
co.fillStyle = prop['chart.text.color'];
|
914
|
+
co.lineWidth = 1;
|
915
|
+
|
916
|
+
co.beginPath();
|
917
|
+
|
918
|
+
for (var i=0; i<=numLabels; ++i) {
|
919
|
+
|
920
|
+
var angle = ((prop['chart.angles.end'] - prop['chart.angles.start']) * (i / numLabels)) + prop['chart.angles.start'];
|
921
|
+
var coords = RG.getRadiusEndPoint(centerx, centery, angle + (((i == 0 || i == numLabels) && prop['chart.border']) ? (i == 0 ? 0.05 : -0.05) : 0), (this.radius * 0.925) - (prop['chart.text.valign'] === 'bottom' ? 15 : 0));
|
922
|
+
|
923
|
+
var angleStart = prop['chart.angles.start'],
|
924
|
+
angleEnd = prop['chart.angles.end'],
|
925
|
+
angleRange = angleEnd - angleStart,
|
926
|
+
angleStart_degrees = angleStart * (180 / RG.PI),
|
927
|
+
angleEnd_degrees = angleEnd * (180 / RG.PI),
|
928
|
+
angleRange_degrees = angleRange * (180 / RG.PI)
|
929
|
+
|
930
|
+
// Vertical alignment
|
931
|
+
valign = prop['chart.text.valign'];
|
932
|
+
|
933
|
+
// Horizontal alignment
|
934
|
+
if (prop['chart.border']) {
|
935
|
+
if (i == 0) {
|
936
|
+
halign = 'left';
|
937
|
+
} else if (i == numLabels) {
|
938
|
+
halign = 'right';
|
939
|
+
} else {
|
940
|
+
halign = 'center'
|
941
|
+
}
|
942
|
+
} else {
|
943
|
+
halign = 'center';
|
944
|
+
}
|
945
|
+
|
946
|
+
var value = ((this.max - this.min) * (i / numLabels)) + this.min;
|
947
|
+
|
948
|
+
RG.text2(this, {
|
949
|
+
'font':text_font,
|
950
|
+
'size':text_size,
|
951
|
+
'x':coords[0],
|
952
|
+
'y':coords[1],
|
953
|
+
'text':RG.numberFormat(this, (value).toFixed(value === 0 ? 0 : decimals),units_pre,units_post),
|
954
|
+
'halign':halign,
|
955
|
+
'valign':valign,
|
956
|
+
'angle':((angleRange_degrees * (1 / numLabels) * i) + angleStart_degrees) - 270,
|
957
|
+
'bounding':false,
|
958
|
+
'boundingFill':(i == 0 || i == numLabels) ? 'white': null,
|
959
|
+
'tag': 'scale'
|
960
|
+
});
|
961
|
+
}
|
962
|
+
};
|
963
|
+
|
964
|
+
|
965
|
+
|
966
|
+
|
967
|
+
/**
|
968
|
+
* This function draws the text readout if specified
|
969
|
+
*/
|
970
|
+
this.drawReadout =
|
971
|
+
this.DrawReadout = function ()
|
972
|
+
{
|
973
|
+
if (prop['chart.value.text']) {
|
974
|
+
co.beginPath();
|
975
|
+
co.fillStyle = prop['chart.text.color'];
|
976
|
+
RG.Text2(this, {'font':prop['chart.text.font'],
|
977
|
+
'size':prop['chart.text.size'],
|
978
|
+
'x':this.centerx,
|
979
|
+
'y':this.centery - prop['chart.text.size'] - 15,
|
980
|
+
'text': prop['chart.value.text.units.pre'] + (this.value).toFixed(prop['chart.value.text.decimals']) + prop['chart.value.text.units.post'],
|
981
|
+
'halign':'center',
|
982
|
+
'valign':'bottom',
|
983
|
+
'bounding':true,
|
984
|
+
'boundingFill':'white',
|
985
|
+
'tag': 'value.text'
|
986
|
+
});
|
987
|
+
|
988
|
+
co.stroke();
|
989
|
+
co.fill();
|
990
|
+
}
|
991
|
+
};
|
992
|
+
|
993
|
+
|
994
|
+
|
995
|
+
|
996
|
+
/**
|
997
|
+
* A placeholder function
|
998
|
+
*
|
999
|
+
* @param object The event object
|
1000
|
+
*/
|
1001
|
+
this.getShape = function (e) {};
|
1002
|
+
|
1003
|
+
|
1004
|
+
|
1005
|
+
|
1006
|
+
/**
|
1007
|
+
* This function returns the pertinent value for a particular click (or other mouse event)
|
1008
|
+
*
|
1009
|
+
* @param obj e The event object
|
1010
|
+
*/
|
1011
|
+
this.getValue = function (e)
|
1012
|
+
{
|
1013
|
+
var mouseXY = RG.getMouseXY(e);
|
1014
|
+
var angle = RG.getAngleByXY(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
|
1015
|
+
|
1016
|
+
// Work out the radius
|
1017
|
+
var radius = RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
|
1018
|
+
if (radius > this.radius) {
|
1019
|
+
return null;
|
1020
|
+
}
|
1021
|
+
|
1022
|
+
|
1023
|
+
if (angle < RG.HALFPI) {
|
1024
|
+
angle += RG.TWOPI;
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
var value = (((angle - prop['chart.angles.start']) / (prop['chart.angles.end'] - prop['chart.angles.start'])) * (this.max - this.min)) + this.min;
|
1028
|
+
|
1029
|
+
value = Math.max(value, this.min);
|
1030
|
+
value = Math.min(value, this.max);
|
1031
|
+
|
1032
|
+
return value;
|
1033
|
+
};
|
1034
|
+
|
1035
|
+
|
1036
|
+
|
1037
|
+
|
1038
|
+
/**
|
1039
|
+
* The getObjectByXY() worker method. Don't call this call:
|
1040
|
+
*
|
1041
|
+
* RGraph.ObjectRegistry.getObjectByXY(e)
|
1042
|
+
*
|
1043
|
+
* @param object e The event object
|
1044
|
+
*/
|
1045
|
+
this.getObjectByXY = function (e)
|
1046
|
+
{
|
1047
|
+
var mouseXY = RGraph.getMouseXY(e);
|
1048
|
+
|
1049
|
+
// Work out the radius
|
1050
|
+
var radius = RG.getHypLength(this.centerx, this.centery, mouseXY[0], mouseXY[1]);
|
1051
|
+
|
1052
|
+
if (
|
1053
|
+
mouseXY[0] > (this.centerx - this.radius)
|
1054
|
+
&& mouseXY[0] < (this.centerx + this.radius)
|
1055
|
+
&& mouseXY[1] > (this.centery - this.radius)
|
1056
|
+
&& mouseXY[1] < (this.centery + this.radius)
|
1057
|
+
&& radius <= this.radius
|
1058
|
+
) {
|
1059
|
+
|
1060
|
+
return this;
|
1061
|
+
}
|
1062
|
+
};
|
1063
|
+
|
1064
|
+
|
1065
|
+
|
1066
|
+
|
1067
|
+
/**
|
1068
|
+
* This method handles the adjusting calculation for when the mouse is moved
|
1069
|
+
*
|
1070
|
+
* @param object e The event object
|
1071
|
+
*/
|
1072
|
+
this.adjusting_mousemove =
|
1073
|
+
this.Adjusting_mousemove = function (e)
|
1074
|
+
{
|
1075
|
+
/**
|
1076
|
+
* Handle adjusting for the Bar
|
1077
|
+
*/
|
1078
|
+
if (prop['chart.adjustable'] && RG.Registry.Get('chart.adjusting') && RG.Registry.Get('chart.adjusting').uid == this.uid) {
|
1079
|
+
this.value = this.getValue(e);
|
1080
|
+
RG.clear(this.canvas);
|
1081
|
+
RG.redrawCanvas(this.canvas);
|
1082
|
+
RG.fireCustomEvent(this, 'onadjust');
|
1083
|
+
}
|
1084
|
+
};
|
1085
|
+
|
1086
|
+
|
1087
|
+
|
1088
|
+
|
1089
|
+
/**
|
1090
|
+
* This method returns the appropriate angle for a value
|
1091
|
+
*
|
1092
|
+
* @param number value The value
|
1093
|
+
*/
|
1094
|
+
this.getAngle = function (value)
|
1095
|
+
{
|
1096
|
+
// Higher than max
|
1097
|
+
if (value > this.max || value < this.min) {
|
1098
|
+
return null;
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
var angle = (((value - this.min) / (this.max - this.min)) * (prop['chart.angles.end'] - prop['chart.angles.start'])) + prop['chart.angles.start'];
|
1102
|
+
|
1103
|
+
return angle;
|
1104
|
+
};
|
1105
|
+
|
1106
|
+
|
1107
|
+
|
1108
|
+
|
1109
|
+
/**
|
1110
|
+
* This allows for easy specification of gradients
|
1111
|
+
*/
|
1112
|
+
this.parseColors = function ()
|
1113
|
+
{
|
1114
|
+
// Save the original colors so that they can be restored when the canvas is reset
|
1115
|
+
if (this.original_colors.length === 0) {
|
1116
|
+
this.original_colors['chart.green.color'] = RG.array_clone(prop['chart.green.color']);
|
1117
|
+
this.original_colors['chart.yellow.color'] = RG.array_clone(prop['chart.yellow.color']);
|
1118
|
+
this.original_colors['chart.red.color'] = RG.array_clone(prop['chart.red.color']);
|
1119
|
+
this.original_colors['chart.colors.ranges'] = RG.array_clone(prop['chart.colors.ranges']);
|
1120
|
+
}
|
1121
|
+
|
1122
|
+
// Parse the basic colors
|
1123
|
+
prop['chart.green.color'] = this.parseSingleColorForGradient(prop['chart.green.color']);
|
1124
|
+
prop['chart.yellow.color'] = this.parseSingleColorForGradient(prop['chart.yellow.color']);
|
1125
|
+
prop['chart.red.color'] = this.parseSingleColorForGradient(prop['chart.red.color']);
|
1126
|
+
|
1127
|
+
// Parse chart.colors.ranges
|
1128
|
+
var ranges = prop['chart.colors.ranges'];
|
1129
|
+
if (ranges && ranges.length) {
|
1130
|
+
for (var i=0; i<ranges.length; ++i) {
|
1131
|
+
ranges[i][2] = this.parseSingleColorForGradient(ranges[i][2]);
|
1132
|
+
}
|
1133
|
+
}
|
1134
|
+
};
|
1135
|
+
|
1136
|
+
|
1137
|
+
|
1138
|
+
|
1139
|
+
/**
|
1140
|
+
* Use this function to reset the object to the post-constructor state. Eg reset colors if
|
1141
|
+
* need be etc
|
1142
|
+
*/
|
1143
|
+
this.reset = function ()
|
1144
|
+
{
|
1145
|
+
};
|
1146
|
+
|
1147
|
+
|
1148
|
+
|
1149
|
+
|
1150
|
+
/**
|
1151
|
+
* This parses a single color value
|
1152
|
+
*/
|
1153
|
+
this.parseSingleColorForGradient = function (color)
|
1154
|
+
{
|
1155
|
+
if (!color || typeof(color) != 'string') {
|
1156
|
+
return color;
|
1157
|
+
}
|
1158
|
+
|
1159
|
+
if (color.match(/^gradient\((.*)\)$/i)) {
|
1160
|
+
|
1161
|
+
var parts = RegExp.$1.split(':');
|
1162
|
+
|
1163
|
+
// Create the gradient
|
1164
|
+
var grad = co.createRadialGradient(this.centerx, this.centery, prop['chart.segment.radius.start'], this.centerx, this.centery, this.radius * 0.85);
|
1165
|
+
|
1166
|
+
var diff = 1 / (parts.length - 1);
|
1167
|
+
|
1168
|
+
for (var j=0; j<parts.length; ++j) {
|
1169
|
+
grad.addColorStop(j * diff, RG.trim(parts[j]));
|
1170
|
+
}
|
1171
|
+
}
|
1172
|
+
|
1173
|
+
return grad ? grad : color;
|
1174
|
+
};
|
1175
|
+
|
1176
|
+
|
1177
|
+
|
1178
|
+
|
1179
|
+
/**
|
1180
|
+
* Using a function to add events makes it easier to facilitate method chaining
|
1181
|
+
*
|
1182
|
+
* @param string type The type of even to add
|
1183
|
+
* @param function func
|
1184
|
+
*/
|
1185
|
+
this.on = function (type, func)
|
1186
|
+
{
|
1187
|
+
if (type.substr(0,2) !== 'on') {
|
1188
|
+
type = 'on' + type;
|
1189
|
+
}
|
1190
|
+
|
1191
|
+
if (typeof this[type] !== 'function') {
|
1192
|
+
this[type] = func;
|
1193
|
+
} else {
|
1194
|
+
RG.addCustomEventListener(this, type, func);
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
return this;
|
1198
|
+
};
|
1199
|
+
|
1200
|
+
|
1201
|
+
|
1202
|
+
|
1203
|
+
/**
|
1204
|
+
* This function runs once only
|
1205
|
+
* (put at the end of the file (before any effects))
|
1206
|
+
*/
|
1207
|
+
this.firstDrawFunc = function ()
|
1208
|
+
{
|
1209
|
+
};
|
1210
|
+
|
1211
|
+
|
1212
|
+
|
1213
|
+
|
1214
|
+
/**
|
1215
|
+
* Meter Grow
|
1216
|
+
*
|
1217
|
+
* This effect gradually increases the represented value
|
1218
|
+
*
|
1219
|
+
* @param An object of options - eg: {frames: 60}
|
1220
|
+
* @param function An optional callback function
|
1221
|
+
*/
|
1222
|
+
this.grow = function ()
|
1223
|
+
{
|
1224
|
+
var obj = this;
|
1225
|
+
|
1226
|
+
obj.currentValue = obj.currentValue || obj.min;
|
1227
|
+
|
1228
|
+
var opt = arguments[0] || {};
|
1229
|
+
var frames = opt.frames || 30;
|
1230
|
+
var frame = 0;
|
1231
|
+
var diff = obj.value - obj.currentValue;
|
1232
|
+
var step = diff / frames;
|
1233
|
+
var callback = arguments[1] || function () {};
|
1234
|
+
var initial = obj.currentValue;
|
1235
|
+
|
1236
|
+
|
1237
|
+
|
1238
|
+
function iterator ()
|
1239
|
+
{
|
1240
|
+
obj.value = initial + (frame++ * step);
|
1241
|
+
|
1242
|
+
RG.clear(obj.canvas);
|
1243
|
+
RG.redrawCanvas(obj.canvas);
|
1244
|
+
|
1245
|
+
if (frame <= frames) {
|
1246
|
+
RG.Effects.updateCanvas(iterator);
|
1247
|
+
} else {
|
1248
|
+
callback(obj);
|
1249
|
+
}
|
1250
|
+
}
|
1251
|
+
|
1252
|
+
iterator();
|
1253
|
+
|
1254
|
+
return this;
|
1255
|
+
};
|
1256
|
+
|
1257
|
+
|
1258
|
+
|
1259
|
+
|
1260
|
+
|
1261
|
+
RG.att(ca);
|
1262
|
+
|
1263
|
+
|
1264
|
+
|
1265
|
+
|
1266
|
+
/**
|
1267
|
+
* Register the object
|
1268
|
+
*/
|
1269
|
+
RG.register(this);
|
1270
|
+
|
1271
|
+
|
1272
|
+
|
1273
|
+
|
1274
|
+
/**
|
1275
|
+
* This is the 'end' of the constructor so if the first argument
|
1276
|
+
* contains configuration data - handle that.
|
1277
|
+
*/
|
1278
|
+
if (parseConfObjectForOptions) {
|
1279
|
+
RG.parseObjectStyleConfig(this, conf.options);
|
1280
|
+
}
|
1281
|
+
};
|