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