1 | /** |
---|
2 | * o------------------------------------------------------------------------------o |
---|
3 | * | This file is part of the RGraph package - you can learn more at: | |
---|
4 | * | | |
---|
5 | * | http://www.rgraph.net | |
---|
6 | * | | |
---|
7 | * | This package is licensed under the RGraph license. For all kinds of business | |
---|
8 | * | purposes there is a small one-time licensing fee to pay and for non | |
---|
9 | * | commercial purposes it is free to use. You can read the full license here: | |
---|
10 | * | | |
---|
11 | * | http://www.rgraph.net/LICENSE.txt | |
---|
12 | * o------------------------------------------------------------------------------o |
---|
13 | */ |
---|
14 | |
---|
15 | if (typeof(RGraph) == 'undefined') RGraph = {}; |
---|
16 | |
---|
17 | /** |
---|
18 | * The scatter graph constructor |
---|
19 | * |
---|
20 | * @param object canvas The cxanvas object |
---|
21 | * @param array data The chart data |
---|
22 | */ |
---|
23 | RGraph.Scatter = function (id, data) |
---|
24 | { |
---|
25 | // Get the canvas and context objects |
---|
26 | this.id = id; |
---|
27 | this.canvas = document.getElementById(id); |
---|
28 | this.canvas.__object__ = this; |
---|
29 | this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null; |
---|
30 | this.max = 0; |
---|
31 | this.coords = []; |
---|
32 | this.data = []; |
---|
33 | this.type = 'scatter'; |
---|
34 | this.isRGraph = true; |
---|
35 | |
---|
36 | |
---|
37 | /** |
---|
38 | * Compatibility with older browsers |
---|
39 | */ |
---|
40 | RGraph.OldBrowserCompat(this.context); |
---|
41 | |
---|
42 | |
---|
43 | // Various config properties |
---|
44 | this.properties = { |
---|
45 | 'chart.background.barcolor1': 'rgba(0,0,0,0)', |
---|
46 | 'chart.background.barcolor2': 'rgba(0,0,0,0)', |
---|
47 | 'chart.background.grid': true, |
---|
48 | 'chart.background.grid.width': 1, |
---|
49 | 'chart.background.grid.color': '#ddd', |
---|
50 | 'chart.background.grid.hsize': 20, |
---|
51 | 'chart.background.grid.vsize': 20, |
---|
52 | 'chart.background.hbars': null, |
---|
53 | 'chart.background.vbars': null, |
---|
54 | 'chart.background.grid.vlines': true, |
---|
55 | 'chart.background.grid.hlines': true, |
---|
56 | 'chart.background.grid.border': true, |
---|
57 | 'chart.background.grid.autofit':false, |
---|
58 | 'chart.background.grid.autofit.numhlines': 7, |
---|
59 | 'chart.background.grid.autofit.numvlines': 20, |
---|
60 | 'chart.text.size': 10, |
---|
61 | 'chart.text.angle': 0, |
---|
62 | 'chart.text.color': 'black', |
---|
63 | 'chart.text.font': 'Verdana', |
---|
64 | 'chart.tooltips.effect': 'fade', |
---|
65 | 'chart.tooltips.hotspot': 3, |
---|
66 | 'chart.tooltips.css.class': 'RGraph_tooltip', |
---|
67 | 'chart.tooltips.highlight': true, |
---|
68 | 'chart.tooltips.coords.adjust': [0,0], |
---|
69 | 'chart.units.pre': '', |
---|
70 | 'chart.units.post': '', |
---|
71 | 'chart.tickmarks': 'cross', |
---|
72 | 'chart.ticksize': 5, |
---|
73 | 'chart.xticks': true, |
---|
74 | 'chart.xaxis': true, |
---|
75 | 'chart.gutter.left': 25, |
---|
76 | 'chart.gutter.right': 25, |
---|
77 | 'chart.gutter.top': 25, |
---|
78 | 'chart.gutter.bottom': 25, |
---|
79 | 'chart.xmax': 0, |
---|
80 | 'chart.ymax': null, |
---|
81 | 'chart.ymin': null, |
---|
82 | 'chart.scale.decimals': null, |
---|
83 | 'chart.scale.point': '.', |
---|
84 | 'chart.scale.thousand': ',', |
---|
85 | 'chart.title': '', |
---|
86 | 'chart.title.background': null, |
---|
87 | 'chart.title.hpos': null, |
---|
88 | 'chart.title.vpos': null, |
---|
89 | 'chart.title.xaxis': '', |
---|
90 | 'chart.title.yaxis': '', |
---|
91 | 'chart.title.xaxis.pos': 0.25, |
---|
92 | 'chart.title.yaxis.pos': 0.25, |
---|
93 | 'chart.labels': [], |
---|
94 | 'chart.labels.ingraph': null, |
---|
95 | 'chart.labels.above': false, |
---|
96 | 'chart.labels.above.size': 8, |
---|
97 | 'chart.labels.above.decimals': 0, |
---|
98 | 'chart.ylabels': true, |
---|
99 | 'chart.ylabels.count': 5, |
---|
100 | 'chart.ylabels.invert': false, |
---|
101 | 'chart.contextmenu': null, |
---|
102 | 'chart.defaultcolor': 'black', |
---|
103 | 'chart.xaxispos': 'bottom', |
---|
104 | 'chart.yaxispos': 'left', |
---|
105 | 'chart.noendxtick': false, |
---|
106 | 'chart.crosshairs': false, |
---|
107 | 'chart.crosshairs.color': '#333', |
---|
108 | 'chart.crosshairs.linewidth': 1, |
---|
109 | 'chart.crosshairs.coords': false, |
---|
110 | 'chart.crosshairs.coords.fixed':true, |
---|
111 | 'chart.crosshairs.coords.fadeout':false, |
---|
112 | 'chart.crosshairs.coords.labels.x': 'X', |
---|
113 | 'chart.crosshairs.coords.labels.y': 'Y', |
---|
114 | 'chart.annotatable': false, |
---|
115 | 'chart.annotate.color': 'black', |
---|
116 | 'chart.line': false, |
---|
117 | 'chart.line.linewidth': 1, |
---|
118 | 'chart.line.colors': ['green', 'red'], |
---|
119 | 'chart.line.shadow.color': 'rgba(0,0,0,0)', |
---|
120 | 'chart.line.shadow.blur': 2, |
---|
121 | 'chart.line.shadow.offsetx': 3, |
---|
122 | 'chart.line.shadow.offsety': 3, |
---|
123 | 'chart.line.stepped': false, |
---|
124 | 'chart.noaxes': false, |
---|
125 | 'chart.key': [], |
---|
126 | 'chart.key.background': 'white', |
---|
127 | 'chart.key.position': 'graph', |
---|
128 | 'chart.key.halign': 'right', |
---|
129 | 'chart.key.shadow': false, |
---|
130 | 'chart.key.shadow.color': '#666', |
---|
131 | 'chart.key.shadow.blur': 3, |
---|
132 | 'chart.key.shadow.offsetx': 2, |
---|
133 | 'chart.key.shadow.offsety': 2, |
---|
134 | 'chart.key.position.gutter.boxed': true, |
---|
135 | 'chart.key.position.x': null, |
---|
136 | 'chart.key.position.y': null, |
---|
137 | 'chart.key.color.shape': 'square', |
---|
138 | 'chart.key.rounded': true, |
---|
139 | 'chart.key.linewidth': 1, |
---|
140 | 'chart.axis.color': 'black', |
---|
141 | 'chart.zoom.factor': 1.5, |
---|
142 | 'chart.zoom.fade.in': true, |
---|
143 | 'chart.zoom.fade.out': true, |
---|
144 | 'chart.zoom.hdir': 'right', |
---|
145 | 'chart.zoom.vdir': 'down', |
---|
146 | 'chart.zoom.frames': 10, |
---|
147 | 'chart.zoom.delay': 50, |
---|
148 | 'chart.zoom.shadow': true, |
---|
149 | 'chart.zoom.mode': 'canvas', |
---|
150 | 'chart.zoom.thumbnail.width': 75, |
---|
151 | 'chart.zoom.thumbnail.height': 75, |
---|
152 | 'chart.zoom.background': true, |
---|
153 | 'chart.zoom.action': 'zoom', |
---|
154 | 'chart.boxplot.width': 8, |
---|
155 | 'chart.resizable': false, |
---|
156 | 'chart.resize.handle.adjust': [0,0], |
---|
157 | 'chart.resize.handle.background': null, |
---|
158 | 'chart.xmin': 0, |
---|
159 | 'chart.labels.specific.align': 'left' |
---|
160 | } |
---|
161 | |
---|
162 | // Handle multiple datasets being given as one argument |
---|
163 | if (arguments[1][0] && arguments[1][0][0] && typeof(arguments[1][0][0][0]) == 'number') { |
---|
164 | // Store the data set(s) |
---|
165 | for (var i=0; i<arguments[1].length; ++i) { |
---|
166 | this.data[i] = arguments[1][i]; |
---|
167 | } |
---|
168 | |
---|
169 | // Handle multiple data sets being supplied as seperate arguments |
---|
170 | } else { |
---|
171 | // Store the data set(s) |
---|
172 | for (var i=1; i<arguments.length; ++i) { |
---|
173 | this.data[i - 1] = arguments[i]; |
---|
174 | } |
---|
175 | } |
---|
176 | |
---|
177 | // Check for support |
---|
178 | if (!this.canvas) { |
---|
179 | alert('[SCATTER] No canvas support'); |
---|
180 | return; |
---|
181 | } |
---|
182 | |
---|
183 | |
---|
184 | /** |
---|
185 | * Set the .getShape commonly named method |
---|
186 | */ |
---|
187 | this.getShape = this.getPoint; |
---|
188 | } |
---|
189 | |
---|
190 | |
---|
191 | /** |
---|
192 | * A simple setter |
---|
193 | * |
---|
194 | * @param string name The name of the property to set |
---|
195 | * @param string value The value of the property |
---|
196 | */ |
---|
197 | RGraph.Scatter.prototype.Set = function (name, value) |
---|
198 | { |
---|
199 | /** |
---|
200 | * This is here because the key expects a name of "chart.colors" |
---|
201 | */ |
---|
202 | if (name == 'chart.line.colors') { |
---|
203 | this.properties['chart.colors'] = value; |
---|
204 | } |
---|
205 | |
---|
206 | /** |
---|
207 | * Allow compatibility with older property names |
---|
208 | */ |
---|
209 | if (name == 'chart.tooltip.hotspot') { |
---|
210 | name = 'chart.tooltips.hotspot'; |
---|
211 | } |
---|
212 | |
---|
213 | /** |
---|
214 | * chart.yaxispos should be left or right |
---|
215 | */ |
---|
216 | if (name == 'chart.yaxispos' && value != 'left' && value != 'right') { |
---|
217 | alert("[SCATTER] chart.yaxispos should be left or right. You've set it to: '" + value + "' Changing it to left"); |
---|
218 | value = 'left'; |
---|
219 | } |
---|
220 | |
---|
221 | /** |
---|
222 | * Check for xaxispos |
---|
223 | */ |
---|
224 | if (name == 'chart.xaxispos' ) { |
---|
225 | if (value != 'bottom' && value != 'center') { |
---|
226 | alert('[SCATTER] (' + this.id + ') chart.xaxispos should be center or bottom. Tried to set it to: ' + value + ' Changing it to center'); |
---|
227 | value = 'center'; |
---|
228 | } |
---|
229 | } |
---|
230 | |
---|
231 | this.properties[name.toLowerCase()] = value; |
---|
232 | } |
---|
233 | |
---|
234 | |
---|
235 | /** |
---|
236 | * A simple getter |
---|
237 | * |
---|
238 | * @param string name The name of the property to set |
---|
239 | */ |
---|
240 | RGraph.Scatter.prototype.Get = function (name) |
---|
241 | { |
---|
242 | return this.properties[name]; |
---|
243 | } |
---|
244 | |
---|
245 | |
---|
246 | /** |
---|
247 | * The function you call to draw the line chart |
---|
248 | */ |
---|
249 | RGraph.Scatter.prototype.Draw = function () |
---|
250 | { |
---|
251 | // MUST be the first thing done! |
---|
252 | if (typeof(this.Get('chart.background.image')) == 'string' && !this.__background_image__) { |
---|
253 | RGraph.DrawBackgroundImage(this); |
---|
254 | return; |
---|
255 | } |
---|
256 | |
---|
257 | /** |
---|
258 | * Fire the onbeforedraw event |
---|
259 | */ |
---|
260 | RGraph.FireCustomEvent(this, 'onbeforedraw'); |
---|
261 | |
---|
262 | /** |
---|
263 | * Clear all of this canvases event handlers (the ones installed by RGraph) |
---|
264 | */ |
---|
265 | RGraph.ClearEventListeners(this.id); |
---|
266 | |
---|
267 | /** |
---|
268 | * This is new in May 2011 and facilitates indiviual gutter settings, |
---|
269 | * eg chart.gutter.left |
---|
270 | */ |
---|
271 | this.gutterLeft = this.Get('chart.gutter.left'); |
---|
272 | this.gutterRight = this.Get('chart.gutter.right'); |
---|
273 | this.gutterTop = this.Get('chart.gutter.top'); |
---|
274 | this.gutterBottom = this.Get('chart.gutter.bottom'); |
---|
275 | |
---|
276 | // Go through all the data points and see if a tooltip has been given |
---|
277 | this.Set('chart.tooltips', false); |
---|
278 | this.hasTooltips = false; |
---|
279 | var overHotspot = false; |
---|
280 | |
---|
281 | // Reset the coords array |
---|
282 | this.coords = []; |
---|
283 | |
---|
284 | if (!RGraph.isIE8()) { |
---|
285 | for (var i=0; i<this.data.length; ++i) { |
---|
286 | for (var j =0;j<this.data[i].length; ++j) { |
---|
287 | if (this.data[i][j] && this.data[i][j][3] && typeof(this.data[i][j][3]) == 'string' && this.data[i][j][3].length) { |
---|
288 | this.Set('chart.tooltips', [1]); // An array |
---|
289 | this.hasTooltips = true; |
---|
290 | } |
---|
291 | } |
---|
292 | } |
---|
293 | } |
---|
294 | |
---|
295 | // Reset the maximum value |
---|
296 | this.max = 0; |
---|
297 | |
---|
298 | // Work out the maximum Y value |
---|
299 | if (this.Get('chart.ymax') && this.Get('chart.ymax') > 0) { |
---|
300 | |
---|
301 | this.scale = []; |
---|
302 | this.max = this.Get('chart.ymax'); |
---|
303 | this.min = this.Get('chart.ymin') ? this.Get('chart.ymin') : 0; |
---|
304 | |
---|
305 | this.scale[0] = ((this.max - this.min) * (1/5)) + this.min; |
---|
306 | this.scale[1] = ((this.max - this.min) * (2/5)) + this.min; |
---|
307 | this.scale[2] = ((this.max - this.min) * (3/5)) + this.min; |
---|
308 | this.scale[3] = ((this.max - this.min) * (4/5)) + this.min; |
---|
309 | this.scale[4] = ((this.max - this.min) * (5/5)) + this.min; |
---|
310 | |
---|
311 | var decimals = this.Get('chart.scale.decimals'); |
---|
312 | |
---|
313 | this.scale = [ |
---|
314 | Number(this.scale[0]).toFixed(decimals), |
---|
315 | Number(this.scale[1]).toFixed(decimals), |
---|
316 | Number(this.scale[2]).toFixed(decimals), |
---|
317 | Number(this.scale[3]).toFixed(decimals), |
---|
318 | Number(this.scale[4]).toFixed(decimals) |
---|
319 | ]; |
---|
320 | |
---|
321 | } else { |
---|
322 | |
---|
323 | var i = 0; |
---|
324 | var j = 0; |
---|
325 | |
---|
326 | for (i=0; i<this.data.length; ++i) { |
---|
327 | for (j=0; j<this.data[i].length; ++j) { |
---|
328 | this.max = Math.max(this.max, typeof(this.data[i][j][1]) == 'object' ? RGraph.array_max(this.data[i][j][1]) : Math.abs(this.data[i][j][1])); |
---|
329 | } |
---|
330 | } |
---|
331 | |
---|
332 | this.scale = RGraph.getScale(this.max, this); |
---|
333 | |
---|
334 | this.max = this.scale[4]; |
---|
335 | this.min = this.Get('chart.ymin') ? this.Get('chart.ymin') : 0; |
---|
336 | |
---|
337 | if (this.min) { |
---|
338 | this.scale[0] = ((this.max - this.min) * (1/5)) + this.min; |
---|
339 | this.scale[1] = ((this.max - this.min) * (2/5)) + this.min; |
---|
340 | this.scale[2] = ((this.max - this.min) * (3/5)) + this.min; |
---|
341 | this.scale[3] = ((this.max - this.min) * (4/5)) + this.min; |
---|
342 | this.scale[4] = ((this.max - this.min) * (5/5)) + this.min; |
---|
343 | } |
---|
344 | |
---|
345 | |
---|
346 | if (typeof(this.Get('chart.scale.decimals')) == 'number') { |
---|
347 | var decimals = this.Get('chart.scale.decimals'); |
---|
348 | |
---|
349 | this.scale = [ |
---|
350 | Number(this.scale[0]).toFixed(decimals), |
---|
351 | Number(this.scale[1]).toFixed(decimals), |
---|
352 | Number(this.scale[2]).toFixed(decimals), |
---|
353 | Number(this.scale[3]).toFixed(decimals), |
---|
354 | Number(this.scale[4]).toFixed(decimals) |
---|
355 | ]; |
---|
356 | } |
---|
357 | } |
---|
358 | |
---|
359 | this.grapharea = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
360 | |
---|
361 | // Progressively Draw the chart |
---|
362 | RGraph.background.Draw(this); |
---|
363 | |
---|
364 | /** |
---|
365 | * Draw any horizontal bars that have been specified |
---|
366 | */ |
---|
367 | if (this.Get('chart.background.hbars') && this.Get('chart.background.hbars').length) { |
---|
368 | RGraph.DrawBars(this); |
---|
369 | } |
---|
370 | |
---|
371 | /** |
---|
372 | * Draw any vertical bars that have been specified |
---|
373 | */ |
---|
374 | if (this.Get('chart.background.vbars') && this.Get('chart.background.vbars').length) { |
---|
375 | this.DrawVBars(); |
---|
376 | } |
---|
377 | |
---|
378 | if (!this.Get('chart.noaxes')) { |
---|
379 | this.DrawAxes(); |
---|
380 | } |
---|
381 | |
---|
382 | this.DrawLabels(); |
---|
383 | |
---|
384 | i = 0; |
---|
385 | for(i=0; i<this.data.length; ++i) { |
---|
386 | this.DrawMarks(i); |
---|
387 | |
---|
388 | // Set the shadow |
---|
389 | this.context.shadowColor = this.Get('chart.line.shadow.color'); |
---|
390 | this.context.shadowOffsetX = this.Get('chart.line.shadow.offsetx'); |
---|
391 | this.context.shadowOffsetY = this.Get('chart.line.shadow.offsety'); |
---|
392 | this.context.shadowBlur = this.Get('chart.line.shadow.blur'); |
---|
393 | |
---|
394 | this.DrawLine(i); |
---|
395 | |
---|
396 | // Turn the shadow off |
---|
397 | RGraph.NoShadow(this); |
---|
398 | } |
---|
399 | |
---|
400 | |
---|
401 | if (this.Get('chart.line')) { |
---|
402 | for (var i=0;i<this.data.length; ++i) { |
---|
403 | this.DrawMarks(i); // Call this again so the tickmarks appear over the line |
---|
404 | } |
---|
405 | } |
---|
406 | |
---|
407 | |
---|
408 | |
---|
409 | /** |
---|
410 | * Setup the context menu if required |
---|
411 | */ |
---|
412 | if (this.Get('chart.contextmenu')) { |
---|
413 | RGraph.ShowContext(this); |
---|
414 | } |
---|
415 | |
---|
416 | /** |
---|
417 | * Install the event handler for tooltips |
---|
418 | */ |
---|
419 | if (this.hasTooltips) { |
---|
420 | |
---|
421 | /** |
---|
422 | * Register all charts |
---|
423 | */ |
---|
424 | RGraph.Register(this); |
---|
425 | |
---|
426 | var overHotspot = false; |
---|
427 | |
---|
428 | var canvas_onmousemove_func = function (e) |
---|
429 | { |
---|
430 | e = RGraph.FixEventObject(e); |
---|
431 | |
---|
432 | var canvas = e.target; |
---|
433 | var obj = canvas.__object__; |
---|
434 | var context = obj.context; |
---|
435 | var mouseCoords = RGraph.getMouseXY(e); |
---|
436 | var point = obj.getPoint(e); |
---|
437 | var overHotspot = false; |
---|
438 | |
---|
439 | if (point) { |
---|
440 | |
---|
441 | var __dataset__ = point[2]; |
---|
442 | var __index__ = point[3]; |
---|
443 | var __text__ = point[4]; |
---|
444 | var overHotspot = true; |
---|
445 | |
---|
446 | if (point[4]) { |
---|
447 | canvas.style.cursor = 'pointer'; |
---|
448 | |
---|
449 | if ( |
---|
450 | !RGraph.Registry.Get('chart.tooltip') || |
---|
451 | RGraph.Registry.Get('chart.tooltip').__text__ != __text__ || |
---|
452 | RGraph.Registry.Get('chart.tooltip').__index__ != __index__ || |
---|
453 | RGraph.Registry.Get('chart.tooltip').__dataset__ != __dataset__ |
---|
454 | ) { |
---|
455 | |
---|
456 | if (obj.Get('chart.tooltips.highlight')) { |
---|
457 | RGraph.Redraw(); |
---|
458 | } |
---|
459 | |
---|
460 | /** |
---|
461 | * Get the tooltip text |
---|
462 | */ |
---|
463 | if (typeof(__text__) == 'function') { |
---|
464 | var text = String(__text__(i)); |
---|
465 | |
---|
466 | } else { |
---|
467 | var text = String(__text__); |
---|
468 | } |
---|
469 | |
---|
470 | RGraph.Tooltip(canvas, text, e.pageX, e.pageY, __index__); |
---|
471 | |
---|
472 | RGraph.Registry.Get('chart.tooltip').__index__ = __index__; |
---|
473 | |
---|
474 | if (RGraph.Registry.Get('chart.tooltip')) { |
---|
475 | RGraph.Registry.Get('chart.tooltip').__dataset__ = __dataset__; |
---|
476 | } |
---|
477 | |
---|
478 | /** |
---|
479 | * Draw a circle around the mark |
---|
480 | */ |
---|
481 | if (obj.Get('chart.tooltips.highlight')) { |
---|
482 | context.beginPath(); |
---|
483 | context.fillStyle = 'rgba(255,255,255,0.5)'; |
---|
484 | context.arc(point[0], point[1], 3, 0, 6.28, 0); |
---|
485 | context.fill(); |
---|
486 | } |
---|
487 | } |
---|
488 | } |
---|
489 | } |
---|
490 | |
---|
491 | /** |
---|
492 | * Reset the pointer |
---|
493 | */ |
---|
494 | if (!overHotspot || !point[4]) { |
---|
495 | canvas.style.cursor = 'default'; |
---|
496 | } |
---|
497 | } |
---|
498 | this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); |
---|
499 | RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); |
---|
500 | } |
---|
501 | |
---|
502 | |
---|
503 | /** |
---|
504 | * Draw the key if necessary |
---|
505 | */ |
---|
506 | if (this.Get('chart.key') && this.Get('chart.key').length) { |
---|
507 | RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.line.colors')); |
---|
508 | } |
---|
509 | |
---|
510 | |
---|
511 | /** |
---|
512 | * Draw " above" labels if enabled |
---|
513 | */ |
---|
514 | if (this.Get('chart.labels.above')) { |
---|
515 | this.DrawAboveLabels(); |
---|
516 | } |
---|
517 | |
---|
518 | /** |
---|
519 | * Draw the "in graph" labels, using the member function, NOT the shared function in RGraph.common.core.js |
---|
520 | */ |
---|
521 | this.DrawInGraphLabels(this); |
---|
522 | |
---|
523 | |
---|
524 | /** |
---|
525 | * Draw crosschairs |
---|
526 | */ |
---|
527 | RGraph.DrawCrosshairs(this); |
---|
528 | |
---|
529 | |
---|
530 | /** |
---|
531 | * If the canvas is annotatable, do install the event handlers |
---|
532 | */ |
---|
533 | if (this.Get('chart.annotatable')) { |
---|
534 | RGraph.Annotate(this); |
---|
535 | } |
---|
536 | |
---|
537 | /** |
---|
538 | * This bit shows the mini zoom window if requested |
---|
539 | */ |
---|
540 | if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { |
---|
541 | RGraph.ShowZoomWindow(this); |
---|
542 | } |
---|
543 | |
---|
544 | |
---|
545 | /** |
---|
546 | * This function enables resizing |
---|
547 | */ |
---|
548 | if (this.Get('chart.resizable')) { |
---|
549 | RGraph.AllowResizing(this); |
---|
550 | } |
---|
551 | |
---|
552 | /** |
---|
553 | * Fire the RGraph ondraw event |
---|
554 | */ |
---|
555 | RGraph.FireCustomEvent(this, 'ondraw'); |
---|
556 | } |
---|
557 | |
---|
558 | |
---|
559 | /** |
---|
560 | * Draws the axes of the scatter graph |
---|
561 | */ |
---|
562 | RGraph.Scatter.prototype.DrawAxes = function () |
---|
563 | { |
---|
564 | var canvas = this.canvas; |
---|
565 | var context = this.context; |
---|
566 | var graphHeight = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
567 | |
---|
568 | context.beginPath(); |
---|
569 | context.strokeStyle = this.Get('chart.axis.color'); |
---|
570 | context.lineWidth = 1; |
---|
571 | |
---|
572 | // Draw the Y axis |
---|
573 | if (this.Get('chart.yaxispos') == 'left') { |
---|
574 | context.moveTo(this.gutterLeft, this.gutterTop); |
---|
575 | context.lineTo(this.gutterLeft, RGraph.GetHeight(this) - this.gutterBottom); |
---|
576 | } else { |
---|
577 | context.moveTo(RGraph.GetWidth(this) - this.gutterRight, this.gutterTop); |
---|
578 | context.lineTo(RGraph.GetWidth(this) - this.gutterRight, RGraph.GetHeight(this) - this.gutterBottom); |
---|
579 | } |
---|
580 | |
---|
581 | |
---|
582 | // Draw the X axis |
---|
583 | if (this.Get('chart.xaxis')) { |
---|
584 | if (this.Get('chart.xaxispos') == 'center') { |
---|
585 | context.moveTo(this.gutterLeft, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2)); |
---|
586 | context.lineTo(RGraph.GetWidth(this) - this.gutterRight, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2)); |
---|
587 | } else { |
---|
588 | context.moveTo(this.gutterLeft, RGraph.GetHeight(this) - this.gutterBottom); |
---|
589 | context.lineTo(RGraph.GetWidth(this) - this.gutterRight, RGraph.GetHeight(this) - this.gutterBottom); |
---|
590 | } |
---|
591 | } |
---|
592 | |
---|
593 | /** |
---|
594 | * Draw the Y tickmarks |
---|
595 | */ |
---|
596 | for (y=this.gutterTop; y < RGraph.GetHeight(this) - this.gutterBottom + (this.Get('chart.xaxispos') == 'center' ? 1 : 0) ; y+=(graphHeight / 5) / 2) { |
---|
597 | |
---|
598 | // This is here to accomodate the X axis being at the center |
---|
599 | if (y == (this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2)) ) continue; |
---|
600 | |
---|
601 | if (this.Get('chart.yaxispos') == 'left') { |
---|
602 | context.moveTo(this.gutterLeft, y); |
---|
603 | context.lineTo(this.gutterLeft - 3, y); |
---|
604 | } else { |
---|
605 | context.moveTo(RGraph.GetWidth(this) - this.gutterRight +3, y); |
---|
606 | context.lineTo(RGraph.GetWidth(this) - this.gutterRight, y); |
---|
607 | } |
---|
608 | } |
---|
609 | |
---|
610 | |
---|
611 | /** |
---|
612 | * Draw the X tickmarks |
---|
613 | */ |
---|
614 | if (this.Get('chart.xticks') && this.Get('chart.xaxis')) { |
---|
615 | |
---|
616 | var x = 0; |
---|
617 | var y = (this.Get('chart.xaxispos') == 'center') ? this.gutterTop + (this.grapharea / 2): (this.canvas.height - this.gutterBottom); |
---|
618 | this.xTickGap = (this.Get('chart.labels') && this.Get('chart.labels').length) ? ((this.canvas.width - this.gutterLeft - this.gutterRight ) / this.Get('chart.labels').length) : (this.canvas.width - this.gutterLeft - this.gutterRight) / 10; |
---|
619 | |
---|
620 | for (x = (this.gutterLeft + (this.Get('chart.yaxispos') == 'left' ? this.xTickGap : 0) ); |
---|
621 | x <= (this.canvas.width - this.gutterRight - (this.Get('chart.yaxispos') == 'left' ? 0 : 1)); |
---|
622 | x += this.xTickGap) { |
---|
623 | |
---|
624 | if (this.Get('chart.yaxispos') == 'left' && this.Get('chart.noendxtick') == true && x == (RGraph.GetWidth(this) - this.gutterLeft) ) { |
---|
625 | continue; |
---|
626 | } else if (this.Get('chart.yaxispos') == 'right' && this.Get('chart.noendxtick') == true && x == this.gutterLeft) { |
---|
627 | continue; |
---|
628 | } |
---|
629 | |
---|
630 | context.moveTo(x, y - (this.Get('chart.xaxispos') == 'center' ? 3 : 0)); |
---|
631 | context.lineTo(x, y + 3); |
---|
632 | } |
---|
633 | } |
---|
634 | |
---|
635 | context.stroke(); |
---|
636 | } |
---|
637 | |
---|
638 | |
---|
639 | |
---|
640 | |
---|
641 | |
---|
642 | |
---|
643 | |
---|
644 | |
---|
645 | |
---|
646 | |
---|
647 | |
---|
648 | /** |
---|
649 | * Draws the labels on the scatter graph |
---|
650 | */ |
---|
651 | RGraph.Scatter.prototype.DrawLabels = function () |
---|
652 | { |
---|
653 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
654 | var font = this.Get('chart.text.font'); |
---|
655 | var xMin = this.Get('chart.xmin'); |
---|
656 | var xMax = this.Get('chart.xmax'); |
---|
657 | var yMax = this.scale[4]; |
---|
658 | var yMin = this.Get('chart.ymin'); |
---|
659 | var text_size = this.Get('chart.text.size'); |
---|
660 | var units_pre = this.Get('chart.units.pre'); |
---|
661 | var units_post = this.Get('chart.units.post'); |
---|
662 | var numYLabels = this.Get('chart.ylabels.count'); |
---|
663 | var invert = this.Get('chart.ylabels.invert'); |
---|
664 | var context = this.context; |
---|
665 | var canvas = this.canvas; |
---|
666 | |
---|
667 | this.halfTextHeight = text_size / 2; |
---|
668 | |
---|
669 | |
---|
670 | this.halfGraphHeight = (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / 2; |
---|
671 | |
---|
672 | /** |
---|
673 | * Draw the Y yaxis labels, be it at the top or center |
---|
674 | */ |
---|
675 | if (this.Get('chart.ylabels')) { |
---|
676 | |
---|
677 | var xPos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft - 5 : RGraph.GetWidth(this) - this.gutterRight + 5; |
---|
678 | var align = this.Get('chart.yaxispos') == 'right' ? 'left' : 'right'; |
---|
679 | |
---|
680 | if (this.Get('chart.xaxispos') == 'center') { |
---|
681 | |
---|
682 | |
---|
683 | /** |
---|
684 | * Specific Y labels |
---|
685 | */ |
---|
686 | if (typeof(this.Get('chart.ylabels.specific')) == 'object') { |
---|
687 | |
---|
688 | var labels = this.Get('chart.ylabels.specific'); |
---|
689 | |
---|
690 | for (var i=0; i<this.Get('chart.ylabels.specific').length; ++i) { |
---|
691 | var y = this.gutterTop + (i * (this.grapharea / (labels.length * 2) ) ); |
---|
692 | RGraph.Text(context, font, text_size, xPos, y, labels[i], 'center', align); |
---|
693 | } |
---|
694 | |
---|
695 | var reversed_labels = RGraph.array_reverse(labels); |
---|
696 | |
---|
697 | for (var i=0; i<reversed_labels.length; ++i) { |
---|
698 | var y = this.gutterTop + (this.grapharea / 2) + ((i+1) * (this.grapharea / (labels.length * 2) ) ); |
---|
699 | |
---|
700 | RGraph.Text(context, font, text_size, xPos, y, reversed_labels[i], 'center', align); |
---|
701 | } |
---|
702 | |
---|
703 | return; |
---|
704 | } |
---|
705 | |
---|
706 | |
---|
707 | if (numYLabels == 1 || numYLabels == 3 || numYLabels == 5) { |
---|
708 | // Draw the top halves labels |
---|
709 | RGraph.Text(context, font, text_size, xPos, this.gutterTop, RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', align); |
---|
710 | |
---|
711 | |
---|
712 | if (numYLabels >= 5) { |
---|
713 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (1/10) ), RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); |
---|
714 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (3/10) ), RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); |
---|
715 | } |
---|
716 | |
---|
717 | if (numYLabels >= 3) { |
---|
718 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (2/10) ), RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); |
---|
719 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (4/10) ), RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); |
---|
720 | } |
---|
721 | |
---|
722 | // Draw the bottom halves labels |
---|
723 | if (numYLabels >= 3) { |
---|
724 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (1/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); |
---|
725 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (3/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); |
---|
726 | } |
---|
727 | |
---|
728 | if (numYLabels == 5) { |
---|
729 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (2/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); |
---|
730 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (4/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); |
---|
731 | } |
---|
732 | |
---|
733 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (5/10) ) + this.halfGraphHeight, '-' + RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', align); |
---|
734 | |
---|
735 | } else if (numYLabels == 10) { |
---|
736 | // 10 Y labels |
---|
737 | var interval = (this.grapharea / numYLabels) / 2; |
---|
738 | |
---|
739 | for (var i=0; i<numYLabels; ++i) { |
---|
740 | RGraph.Text(context, font, text_size, xPos,this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (i/20) ),RGraph.number_format(this, |
---|
741 | |
---|
742 | (this.max - (this.max * (i/10))).toFixed(this.Get('chart.scale.decimals')), |
---|
743 | |
---|
744 | units_pre, units_post),'center', align); |
---|
745 | RGraph.Text(context, font, text_size, xPos,this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (i/20) ) + (this.grapharea / 2) + (this.grapharea / 20),'-' + RGraph.number_format(this, ((this.max * (i/10)) + (this.max * (1/10))).toFixed((this.Get('chart.scale.decimals'))), units_pre, units_post), 'center', align); |
---|
746 | } |
---|
747 | |
---|
748 | } else { |
---|
749 | alert('[SCATTER SCALE] Number of Y labels can be 1/3/5/10 only'); |
---|
750 | } |
---|
751 | |
---|
752 | } else { |
---|
753 | |
---|
754 | var xPos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft - 5 : RGraph.GetWidth(this) - this.gutterRight + 5; |
---|
755 | var align = this.Get('chart.yaxispos') == 'right' ? 'left' : 'right'; |
---|
756 | |
---|
757 | /** |
---|
758 | * Specific Y labels |
---|
759 | */ |
---|
760 | if (typeof(this.Get('chart.ylabels.specific')) == 'object' && this.Get('chart.ylabels.specific')) { |
---|
761 | |
---|
762 | var labels = this.Get('chart.ylabels.specific'); |
---|
763 | |
---|
764 | for (var i=0; i<this.Get('chart.ylabels.specific').length; ++i) { |
---|
765 | var y = this.gutterTop + (i * (this.grapharea / labels.length) ); |
---|
766 | |
---|
767 | RGraph.Text(context, font, text_size, xPos, y, labels[i], 'center', align); |
---|
768 | } |
---|
769 | |
---|
770 | return; |
---|
771 | } |
---|
772 | |
---|
773 | if (numYLabels == 1 || numYLabels == 3 || numYLabels == 5) { |
---|
774 | if (invert) { |
---|
775 | RGraph.Text(context, font, text_size, xPos, this.gutterTop, RGraph.number_format(this, 0, units_pre, units_post), 'center', align); |
---|
776 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (5/5) ), RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', align); |
---|
777 | |
---|
778 | if (numYLabels >= 5) { |
---|
779 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (2/5) ), RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); |
---|
780 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (4/5) ), RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); |
---|
781 | } |
---|
782 | |
---|
783 | if (numYLabels >= 3) { |
---|
784 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (3/5) ), RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); |
---|
785 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (1/5) ), RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); |
---|
786 | } |
---|
787 | } else { |
---|
788 | RGraph.Text(context, font, text_size, xPos, this.gutterTop, RGraph.number_format(this, this.scale[4], units_pre, units_post), 'center', align); |
---|
789 | |
---|
790 | if (numYLabels >= 5) { |
---|
791 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (1/5) ), RGraph.number_format(this, this.scale[3], units_pre, units_post), 'center', align); |
---|
792 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (3/5) ), RGraph.number_format(this, this.scale[1], units_pre, units_post), 'center', align); |
---|
793 | } |
---|
794 | |
---|
795 | if (numYLabels >= 3) { |
---|
796 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (2/5) ), RGraph.number_format(this, this.scale[2], units_pre, units_post), 'center', align); |
---|
797 | RGraph.Text(context, font, text_size, xPos, this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * (4/5) ), RGraph.number_format(this, this.scale[0], units_pre, units_post), 'center', align); |
---|
798 | } |
---|
799 | } |
---|
800 | } else if (numYLabels == 10) { |
---|
801 | var interval = (this.grapharea / numYLabels) / 2; |
---|
802 | if (invert) { |
---|
803 | for (var i=numYLabels; i>=0; --i) { |
---|
804 | RGraph.Text(context, font, text_size, xPos,this.gutterTop + ((RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) * ((10-i)/10) ), |
---|
805 | |
---|
806 | RGraph.number_format(this,(this.max - (this.max * (i/10))).toFixed((this.Get('chart.scale.decimals'))), units_pre, units_post), |
---|
807 | |
---|
808 | 'center', align); |
---|
809 | } |
---|
810 | } else { |
---|
811 | // 10 Y labels |
---|
812 | for (var i=0; i<numYLabels; ++i) { |
---|
813 | |
---|
814 | RGraph.Text(context, font, text_size, xPos,this.gutterTop + ((this.canvas.height - this.gutterTop - this.gutterBottom) * (i/10) ), |
---|
815 | |
---|
816 | RGraph.number_format(this, |
---|
817 | (this.max - ((this.max - this.min) * (i/10))).toFixed((this.Get('chart.scale.decimals'))), |
---|
818 | units_pre, |
---|
819 | units_post), |
---|
820 | 'center', align); |
---|
821 | } |
---|
822 | } |
---|
823 | } else { |
---|
824 | alert('[SCATTER SCALE] Number of Y labels can be 1/3/5/10 only'); |
---|
825 | } |
---|
826 | |
---|
827 | if (this.Get('chart.ymin')) { |
---|
828 | RGraph.Text(context, font, text_size, xPos, this.canvas.height - this.gutterBottom,RGraph.number_format(this, this.Get('chart.ymin').toFixed(this.Get('chart.scale.decimals')), units_pre, units_post),'center', align); |
---|
829 | } |
---|
830 | } |
---|
831 | } |
---|
832 | |
---|
833 | |
---|
834 | |
---|
835 | |
---|
836 | |
---|
837 | |
---|
838 | // Put the text on the X axis |
---|
839 | var graphArea = RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight; |
---|
840 | var xInterval = graphArea / this.Get('chart.labels').length; |
---|
841 | var xPos = this.gutterLeft; |
---|
842 | var yPos = (RGraph.GetHeight(this) - this.gutterBottom) + 15; |
---|
843 | var labels = this.Get('chart.labels'); |
---|
844 | |
---|
845 | /** |
---|
846 | * Text angle |
---|
847 | */ |
---|
848 | var angle = 0; |
---|
849 | var valign = null; |
---|
850 | var halign = 'center'; |
---|
851 | |
---|
852 | if (this.Get('chart.text.angle') > 0) { |
---|
853 | angle = -1 * this.Get('chart.text.angle'); |
---|
854 | valign = 'center'; |
---|
855 | halign = 'right'; |
---|
856 | yPos -= 10; |
---|
857 | } |
---|
858 | |
---|
859 | for (i=0; i<labels.length; ++i) { |
---|
860 | |
---|
861 | if (typeof(labels[i]) == 'object') { |
---|
862 | |
---|
863 | if (this.Get('chart.labels.specific.align') == 'center') { |
---|
864 | var rightEdge = 0; |
---|
865 | |
---|
866 | if (labels[i+1] && labels[i+1][1]) { |
---|
867 | rightEdge = labels[i+1][1]; |
---|
868 | } else { |
---|
869 | rightEdge = this.Get('chart.xmax'); |
---|
870 | } |
---|
871 | |
---|
872 | var offset = (rightEdge - labels[i][1]) / 2; |
---|
873 | |
---|
874 | } else { |
---|
875 | var offset = 0; |
---|
876 | } |
---|
877 | |
---|
878 | |
---|
879 | RGraph.Text(context, |
---|
880 | font, |
---|
881 | this.Get('chart.text.size'), |
---|
882 | this.gutterLeft + (graphArea * ((labels[i][1] - xMin + offset) / (this.Get('chart.xmax') - xMin))) + 5, |
---|
883 | yPos, |
---|
884 | String(labels[i][0]), |
---|
885 | valign, |
---|
886 | angle != 0 ? 'right' : (this.Get('chart.labels.specific.align') == 'center' ? 'center' : 'left'), |
---|
887 | null, |
---|
888 | angle |
---|
889 | ); |
---|
890 | |
---|
891 | /** |
---|
892 | * Draw the gray indicator line |
---|
893 | */ |
---|
894 | this.context.beginPath(); |
---|
895 | this.context.strokeStyle = '#bbb'; |
---|
896 | this.context.moveTo(this.gutterLeft + (graphArea * ((labels[i][1] - xMin)/ (this.Get('chart.xmax') - xMin))), RGraph.GetHeight(this) - this.gutterBottom); |
---|
897 | this.context.lineTo(this.gutterLeft + (graphArea * ((labels[i][1] - xMin)/ (this.Get('chart.xmax') - xMin))), RGraph.GetHeight(this) - this.gutterBottom + 20); |
---|
898 | this.context.stroke(); |
---|
899 | |
---|
900 | } else { |
---|
901 | RGraph.Text(context, font, this.Get('chart.text.size'), xPos + (this.xTickGap / 2), yPos, String(labels[i]), valign, halign, null, angle); |
---|
902 | } |
---|
903 | |
---|
904 | // Do this for the next time around |
---|
905 | xPos += xInterval; |
---|
906 | } |
---|
907 | |
---|
908 | /** |
---|
909 | * Draw the final indicator line |
---|
910 | */ |
---|
911 | if (typeof(labels[0]) == 'object') { |
---|
912 | this.context.beginPath(); |
---|
913 | this.context.strokeStyle = '#bbb'; |
---|
914 | this.context.moveTo(this.gutterLeft + graphArea, RGraph.GetHeight(this) - this.gutterBottom); |
---|
915 | this.context.lineTo(this.gutterLeft + graphArea, RGraph.GetHeight(this) - this.gutterBottom + 20); |
---|
916 | this.context.stroke(); |
---|
917 | } |
---|
918 | } |
---|
919 | |
---|
920 | |
---|
921 | |
---|
922 | |
---|
923 | |
---|
924 | |
---|
925 | |
---|
926 | |
---|
927 | |
---|
928 | |
---|
929 | |
---|
930 | |
---|
931 | |
---|
932 | |
---|
933 | /** |
---|
934 | * Draws the actual scatter graph marks |
---|
935 | * |
---|
936 | * @param i integer The dataset index |
---|
937 | */ |
---|
938 | RGraph.Scatter.prototype.DrawMarks = function (i) |
---|
939 | { |
---|
940 | /** |
---|
941 | * Reset the coords array |
---|
942 | */ |
---|
943 | this.coords[i] = []; |
---|
944 | |
---|
945 | /** |
---|
946 | * Plot the values |
---|
947 | */ |
---|
948 | var xmax = this.Get('chart.xmax'); |
---|
949 | var default_color = this.Get('chart.defaultcolor'); |
---|
950 | |
---|
951 | for (var j=0; j<this.data[i].length; ++j) { |
---|
952 | /** |
---|
953 | * This is here because tooltips are optional |
---|
954 | */ |
---|
955 | var data_point = this.data[i]; |
---|
956 | |
---|
957 | var xCoord = data_point[j][0]; |
---|
958 | var yCoord = data_point[j][1]; |
---|
959 | var color = data_point[j][2] ? data_point[j][2] : default_color; |
---|
960 | var tooltip = (data_point[j] && data_point[j][3]) ? data_point[j][3] : null; |
---|
961 | |
---|
962 | |
---|
963 | this.DrawMark( |
---|
964 | i, |
---|
965 | xCoord, |
---|
966 | yCoord, |
---|
967 | xmax, |
---|
968 | this.scale[4], |
---|
969 | color, |
---|
970 | tooltip, |
---|
971 | this.coords[i], |
---|
972 | data_point |
---|
973 | ); |
---|
974 | } |
---|
975 | } |
---|
976 | |
---|
977 | |
---|
978 | /** |
---|
979 | * Draws a single scatter mark |
---|
980 | */ |
---|
981 | RGraph.Scatter.prototype.DrawMark = function (index, x, y, xMax, yMax, color, tooltip, coords, data) |
---|
982 | { |
---|
983 | /** |
---|
984 | * Inverted Y scale handling |
---|
985 | */ |
---|
986 | if (this.Get('chart.ylabels.invert')) { |
---|
987 | if (typeof(y) == 'number') { |
---|
988 | y = yMax - y; |
---|
989 | } |
---|
990 | } |
---|
991 | |
---|
992 | var tickmarks = this.Get('chart.tickmarks'); |
---|
993 | var tickSize = this.Get('chart.ticksize'); |
---|
994 | var xMin = this.Get('chart.xmin'); |
---|
995 | var x = ((x - xMin) / (xMax - xMin)) * (RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight); |
---|
996 | var originalX = x; |
---|
997 | var originalY = y; |
---|
998 | |
---|
999 | |
---|
1000 | /** |
---|
1001 | * This allows chart.tickmarks to be an array |
---|
1002 | */ |
---|
1003 | |
---|
1004 | if (tickmarks && typeof(tickmarks) == 'object') { |
---|
1005 | tickmarks = tickmarks[index]; |
---|
1006 | } |
---|
1007 | |
---|
1008 | |
---|
1009 | /** |
---|
1010 | * This allows chart.ticksize to be an array |
---|
1011 | */ |
---|
1012 | if (typeof(tickSize) == 'object') { |
---|
1013 | var tickSize = tickSize[index]; |
---|
1014 | var halfTickSize = tickSize / 2; |
---|
1015 | } else { |
---|
1016 | var halfTickSize = tickSize / 2; |
---|
1017 | } |
---|
1018 | |
---|
1019 | |
---|
1020 | /** |
---|
1021 | * This bit is for boxplots only |
---|
1022 | */ |
---|
1023 | if ( typeof(y) == 'object' |
---|
1024 | && typeof(y[0]) == 'number' |
---|
1025 | && typeof(y[1]) == 'number' |
---|
1026 | && typeof(y[2]) == 'number' |
---|
1027 | && typeof(y[3]) == 'number' |
---|
1028 | && typeof(y[4]) == 'number' |
---|
1029 | ) { |
---|
1030 | |
---|
1031 | var yMin = this.Get('chart.ymin') ? this.Get('chart.ymin') : 0; |
---|
1032 | this.Set('chart.boxplot', true); |
---|
1033 | this.graphheight = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
1034 | |
---|
1035 | if (this.Get('chart.xaxispos') == 'center') { |
---|
1036 | this.graphheight /= 2; |
---|
1037 | } |
---|
1038 | |
---|
1039 | var y0 = (this.graphheight) - ((y[4] - yMin) / (yMax - yMin)) * (this.graphheight); |
---|
1040 | var y1 = (this.graphheight) - ((y[3] - yMin) / (yMax - yMin)) * (this.graphheight); |
---|
1041 | var y2 = (this.graphheight) - ((y[2] - yMin) / (yMax - yMin)) * (this.graphheight); |
---|
1042 | var y3 = (this.graphheight) - ((y[1] - yMin) / (yMax - yMin)) * (this.graphheight); |
---|
1043 | var y4 = (this.graphheight) - ((y[0] - yMin) / (yMax - yMin)) * (this.graphheight); |
---|
1044 | |
---|
1045 | /** |
---|
1046 | * Inverted labels |
---|
1047 | */ |
---|
1048 | if (this.Get('chart.ylabels.invert')) { |
---|
1049 | y0 = this.graphheight - y0; |
---|
1050 | y1 = this.graphheight - y1; |
---|
1051 | y2 = this.graphheight - y2; |
---|
1052 | y3 = this.graphheight - y3; |
---|
1053 | y4 = this.graphheight - y4; |
---|
1054 | } |
---|
1055 | |
---|
1056 | var col1 = y[5]; |
---|
1057 | var col2 = y[6]; |
---|
1058 | |
---|
1059 | // Override the boxWidth |
---|
1060 | if (typeof(y[7]) == 'number') { |
---|
1061 | var boxWidth = y[7]; |
---|
1062 | } |
---|
1063 | |
---|
1064 | var y = this.graphheight - y2; |
---|
1065 | |
---|
1066 | } else { |
---|
1067 | var yMin = this.Get('chart.ymin') ? this.Get('chart.ymin') : 0; |
---|
1068 | var y = (( (y - yMin) / (yMax - yMin)) * (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom)); |
---|
1069 | } |
---|
1070 | |
---|
1071 | /** |
---|
1072 | * Account for the X axis being at the centre |
---|
1073 | */ |
---|
1074 | if (this.Get('chart.xaxispos') == 'center') { |
---|
1075 | y /= 2; |
---|
1076 | y += this.halfGraphHeight; |
---|
1077 | } |
---|
1078 | |
---|
1079 | // This is so that points are on the graph, and not the gutter |
---|
1080 | x += this.gutterLeft; |
---|
1081 | y = RGraph.GetHeight(this) - this.gutterBottom - y; |
---|
1082 | |
---|
1083 | this.context.beginPath(); |
---|
1084 | |
---|
1085 | // Color |
---|
1086 | this.context.strokeStyle = color; |
---|
1087 | |
---|
1088 | /** |
---|
1089 | * Boxplots |
---|
1090 | */ |
---|
1091 | if ( this.Get('chart.boxplot') |
---|
1092 | && typeof(y0) == 'number' |
---|
1093 | && typeof(y1) == 'number' |
---|
1094 | && typeof(y2) == 'number' |
---|
1095 | && typeof(y3) == 'number' |
---|
1096 | && typeof(y4) == 'number' |
---|
1097 | ) { |
---|
1098 | |
---|
1099 | var boxWidth = boxWidth ? boxWidth : this.Get('chart.boxplot.width'); |
---|
1100 | var halfBoxWidth = boxWidth / 2; |
---|
1101 | |
---|
1102 | this.context.beginPath(); |
---|
1103 | |
---|
1104 | // Draw the upper coloured box if a value is specified |
---|
1105 | if (col1) { |
---|
1106 | this.context.fillStyle = col1; |
---|
1107 | this.context.fillRect(x - halfBoxWidth, y1 + this.gutterTop, boxWidth, y2 - y1); |
---|
1108 | } |
---|
1109 | |
---|
1110 | // Draw the lower coloured box if a value is specified |
---|
1111 | if (col2) { |
---|
1112 | this.context.fillStyle = col2; |
---|
1113 | this.context.fillRect(x - halfBoxWidth, y2 + this.gutterTop, boxWidth, y3 - y2); |
---|
1114 | } |
---|
1115 | |
---|
1116 | this.context.strokeRect(x - halfBoxWidth, y1 + this.gutterTop, boxWidth, y3 - y1); |
---|
1117 | this.context.stroke(); |
---|
1118 | |
---|
1119 | // Now draw the whiskers |
---|
1120 | this.context.beginPath(); |
---|
1121 | this.context.moveTo(x - halfBoxWidth, y0 + this.gutterTop); |
---|
1122 | this.context.lineTo(x + halfBoxWidth, y0 + this.gutterTop); |
---|
1123 | |
---|
1124 | this.context.moveTo(x, y0 + this.gutterTop); |
---|
1125 | this.context.lineTo(x, y1 + this.gutterTop); |
---|
1126 | |
---|
1127 | this.context.moveTo(x - halfBoxWidth, y4 + this.gutterTop); |
---|
1128 | this.context.lineTo(x + halfBoxWidth, y4 + this.gutterTop); |
---|
1129 | |
---|
1130 | this.context.moveTo(x, y4 + this.gutterTop); |
---|
1131 | this.context.lineTo(x, y3 + this.gutterTop); |
---|
1132 | |
---|
1133 | this.context.stroke(); |
---|
1134 | } |
---|
1135 | |
---|
1136 | |
---|
1137 | /** |
---|
1138 | * Draw the tickmark, but not for boxplots |
---|
1139 | */ |
---|
1140 | if (!y0 && !y1 && !y2 && !y3 && !y4) { |
---|
1141 | |
---|
1142 | this.graphheight = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
1143 | |
---|
1144 | |
---|
1145 | |
---|
1146 | if (tickmarks == 'circle') { |
---|
1147 | this.context.arc(x, y, halfTickSize, 0, 6.28, 0); |
---|
1148 | this.context.fillStyle = color; |
---|
1149 | this.context.fill(); |
---|
1150 | |
---|
1151 | } else if (tickmarks == 'plus') { |
---|
1152 | |
---|
1153 | this.context.moveTo(x, y - halfTickSize); |
---|
1154 | this.context.lineTo(x, y + halfTickSize); |
---|
1155 | this.context.moveTo(x - halfTickSize, y); |
---|
1156 | this.context.lineTo(x + halfTickSize, y); |
---|
1157 | this.context.stroke(); |
---|
1158 | |
---|
1159 | } else if (tickmarks == 'square') { |
---|
1160 | this.context.strokeStyle = color; |
---|
1161 | this.context.fillStyle = color; |
---|
1162 | this.context.fillRect( |
---|
1163 | x - halfTickSize, |
---|
1164 | y - halfTickSize, |
---|
1165 | tickSize, |
---|
1166 | tickSize |
---|
1167 | ); |
---|
1168 | //this.context.fill(); |
---|
1169 | |
---|
1170 | } else if (tickmarks == 'cross') { |
---|
1171 | |
---|
1172 | this.context.moveTo(x - halfTickSize, y - halfTickSize); |
---|
1173 | this.context.lineTo(x + halfTickSize, y + halfTickSize); |
---|
1174 | this.context.moveTo(x + halfTickSize, y - halfTickSize); |
---|
1175 | this.context.lineTo(x - halfTickSize, y + halfTickSize); |
---|
1176 | |
---|
1177 | this.context.stroke(); |
---|
1178 | |
---|
1179 | /** |
---|
1180 | * Diamond shape tickmarks |
---|
1181 | */ |
---|
1182 | } else if (tickmarks == 'diamond') { |
---|
1183 | this.context.fillStyle = this.context.strokeStyle; |
---|
1184 | |
---|
1185 | this.context.moveTo(x, y - halfTickSize); |
---|
1186 | this.context.lineTo(x + halfTickSize, y); |
---|
1187 | this.context.lineTo(x, y + halfTickSize); |
---|
1188 | this.context.lineTo(x - halfTickSize, y); |
---|
1189 | this.context.lineTo(x, y - halfTickSize); |
---|
1190 | |
---|
1191 | this.context.fill(); |
---|
1192 | this.context.stroke(); |
---|
1193 | |
---|
1194 | /** |
---|
1195 | * Custom tickmark style |
---|
1196 | */ |
---|
1197 | } else if (typeof(tickmarks) == 'function') { |
---|
1198 | |
---|
1199 | var graphWidth = RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight |
---|
1200 | var xVal = ((x - this.gutterLeft) / graphWidth) * xMax; |
---|
1201 | var yVal = ((this.graphheight - (y - this.gutterTop)) / this.graphheight) * yMax; |
---|
1202 | |
---|
1203 | tickmarks(this, data, x, y, xVal, yVal, xMax, yMax, color) |
---|
1204 | |
---|
1205 | /** |
---|
1206 | * No tickmarks |
---|
1207 | */ |
---|
1208 | } else if (tickmarks == null) { |
---|
1209 | |
---|
1210 | /** |
---|
1211 | * Unknown tickmark type |
---|
1212 | */ |
---|
1213 | } else { |
---|
1214 | alert('[SCATTER] (' + this.id + ') Unknown tickmark style: ' + tickmarks ); |
---|
1215 | } |
---|
1216 | } |
---|
1217 | |
---|
1218 | /** |
---|
1219 | * Add the tickmark to the coords array |
---|
1220 | */ |
---|
1221 | coords.push([x, y, tooltip]); |
---|
1222 | } |
---|
1223 | |
---|
1224 | |
---|
1225 | /** |
---|
1226 | * Draws an optional line connecting the tick marks. |
---|
1227 | * |
---|
1228 | * @param i The index of the dataset to use |
---|
1229 | */ |
---|
1230 | RGraph.Scatter.prototype.DrawLine = function (i) |
---|
1231 | { |
---|
1232 | if (this.Get('chart.line') && this.coords[i].length >= 2) { |
---|
1233 | |
---|
1234 | this.context.lineCap = 'round'; |
---|
1235 | this.context.lineJoin = 'round'; |
---|
1236 | this.context.lineWidth = this.GetLineWidth(i);// i is the index of the set of coordinates |
---|
1237 | this.context.strokeStyle = this.Get('chart.line.colors')[i]; |
---|
1238 | this.context.beginPath(); |
---|
1239 | |
---|
1240 | var len = this.coords[i].length; |
---|
1241 | |
---|
1242 | for (var j=0; j<this.coords[i].length; ++j) { |
---|
1243 | |
---|
1244 | var xPos = this.coords[i][j][0]; |
---|
1245 | var yPos = this.coords[i][j][1]; |
---|
1246 | |
---|
1247 | if (j == 0) { |
---|
1248 | this.context.moveTo(xPos, yPos); |
---|
1249 | } else { |
---|
1250 | |
---|
1251 | // Stepped? |
---|
1252 | var stepped = this.Get('chart.line.stepped'); |
---|
1253 | |
---|
1254 | if ( (typeof(stepped) == 'boolean' && stepped) |
---|
1255 | || (typeof(stepped) == 'object' && stepped[i]) |
---|
1256 | ) { |
---|
1257 | this.context.lineTo(this.coords[i][j][0], this.coords[i][j - 1][1]); |
---|
1258 | } |
---|
1259 | |
---|
1260 | this.context.lineTo(xPos, yPos); |
---|
1261 | } |
---|
1262 | } |
---|
1263 | |
---|
1264 | this.context.stroke(); |
---|
1265 | } |
---|
1266 | |
---|
1267 | /** |
---|
1268 | * Set the linewidth back to 1 |
---|
1269 | */ |
---|
1270 | this.context.lineWidth = 1; |
---|
1271 | } |
---|
1272 | |
---|
1273 | |
---|
1274 | /** |
---|
1275 | * Returns the linewidth |
---|
1276 | * |
---|
1277 | * @param number i The index of the "line" (/set of coordinates) |
---|
1278 | */ |
---|
1279 | RGraph.Scatter.prototype.GetLineWidth = function (i) |
---|
1280 | { |
---|
1281 | var linewidth = this.Get('chart.line.linewidth'); |
---|
1282 | |
---|
1283 | if (typeof(linewidth) == 'number') { |
---|
1284 | return linewidth; |
---|
1285 | |
---|
1286 | } else if (typeof(linewidth) == 'object') { |
---|
1287 | if (linewidth[i]) { |
---|
1288 | return linewidth[i]; |
---|
1289 | } else { |
---|
1290 | return linewidth[0]; |
---|
1291 | } |
---|
1292 | |
---|
1293 | alert('[SCATTER] Error! chart.linewidth should be a single number or an array of one or more numbers'); |
---|
1294 | } |
---|
1295 | } |
---|
1296 | |
---|
1297 | |
---|
1298 | /** |
---|
1299 | * Draws vertical bars. Line chart doesn't use a horizontal scale, hence this function |
---|
1300 | * is not common |
---|
1301 | */ |
---|
1302 | RGraph.Scatter.prototype.DrawVBars = function () |
---|
1303 | { |
---|
1304 | var canvas = this.canvas; |
---|
1305 | var context = this.context; |
---|
1306 | var vbars = this.Get('chart.background.vbars'); |
---|
1307 | var graphWidth = RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight; |
---|
1308 | |
---|
1309 | if (vbars) { |
---|
1310 | |
---|
1311 | var xmax = this.Get('chart.xmax'); |
---|
1312 | |
---|
1313 | for (var i=0; i<vbars.length; ++i) { |
---|
1314 | var startX = ((vbars[i][0] / xmax) * graphWidth) + this.gutterLeft; |
---|
1315 | var width = (vbars[i][1] / xmax) * graphWidth; |
---|
1316 | |
---|
1317 | context.beginPath(); |
---|
1318 | context.fillStyle = vbars[i][2]; |
---|
1319 | context.fillRect(startX, this.gutterTop, width, (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom)); |
---|
1320 | context.fill(); |
---|
1321 | } |
---|
1322 | } |
---|
1323 | } |
---|
1324 | |
---|
1325 | |
---|
1326 | |
---|
1327 | |
---|
1328 | |
---|
1329 | /** |
---|
1330 | * Draws in-graph labels. |
---|
1331 | * |
---|
1332 | * @param object obj The graph object |
---|
1333 | */ |
---|
1334 | RGraph.Scatter.prototype.DrawInGraphLabels = function (obj) |
---|
1335 | { |
---|
1336 | var canvas = obj.canvas; |
---|
1337 | var context = obj.context; |
---|
1338 | var labels = obj.Get('chart.labels.ingraph'); |
---|
1339 | var labels_processed = []; |
---|
1340 | |
---|
1341 | // Defaults |
---|
1342 | var fgcolor = 'black'; |
---|
1343 | var bgcolor = 'white'; |
---|
1344 | var direction = 1; |
---|
1345 | |
---|
1346 | if (!labels) { |
---|
1347 | return; |
---|
1348 | } |
---|
1349 | |
---|
1350 | /** |
---|
1351 | * Preprocess the labels array. Numbers are expanded |
---|
1352 | */ |
---|
1353 | for (var i=0; i<labels.length; ++i) { |
---|
1354 | if (typeof(labels[i]) == 'number') { |
---|
1355 | for (var j=0; j<labels[i]; ++j) { |
---|
1356 | labels_processed.push(null); |
---|
1357 | } |
---|
1358 | } else if (typeof(labels[i]) == 'string' || typeof(labels[i]) == 'object') { |
---|
1359 | labels_processed.push(labels[i]); |
---|
1360 | |
---|
1361 | } else { |
---|
1362 | labels_processed.push(''); |
---|
1363 | } |
---|
1364 | } |
---|
1365 | |
---|
1366 | /** |
---|
1367 | * Turn off any shadow |
---|
1368 | */ |
---|
1369 | RGraph.NoShadow(obj); |
---|
1370 | |
---|
1371 | if (labels_processed && labels_processed.length > 0) { |
---|
1372 | |
---|
1373 | var i=0; |
---|
1374 | |
---|
1375 | for (var set=0; set<obj.coords.length; ++set) { |
---|
1376 | for (var point = 0; point<obj.coords[set].length; ++point) { |
---|
1377 | if (labels_processed[i]) { |
---|
1378 | var x = obj.coords[set][point][0]; |
---|
1379 | var y = obj.coords[set][point][1]; |
---|
1380 | var length = typeof(labels_processed[i][4]) == 'number' ? labels_processed[i][4] : 25; |
---|
1381 | |
---|
1382 | var text_x = x; |
---|
1383 | var text_y = y - 5 - length; |
---|
1384 | |
---|
1385 | context.moveTo(x, y - 5); |
---|
1386 | context.lineTo(x, y - 5 - length); |
---|
1387 | |
---|
1388 | context.stroke(); |
---|
1389 | context.beginPath(); |
---|
1390 | |
---|
1391 | // This draws the arrow |
---|
1392 | context.moveTo(x, y - 5); |
---|
1393 | context.lineTo(x - 3, y - 10); |
---|
1394 | context.lineTo(x + 3, y - 10); |
---|
1395 | context.closePath(); |
---|
1396 | |
---|
1397 | |
---|
1398 | context.beginPath(); |
---|
1399 | |
---|
1400 | // Fore ground color |
---|
1401 | context.fillStyle = (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][1]) == 'string') ? labels_processed[i][1] : 'black'; |
---|
1402 | |
---|
1403 | RGraph.Text(context, |
---|
1404 | obj.Get('chart.text.font'), |
---|
1405 | obj.Get('chart.text.size'), |
---|
1406 | text_x, |
---|
1407 | text_y, |
---|
1408 | (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][0]) == 'string') ? labels_processed[i][0] : labels_processed[i], |
---|
1409 | 'bottom', |
---|
1410 | 'center', |
---|
1411 | true, |
---|
1412 | null, |
---|
1413 | (typeof(labels_processed[i]) == 'object' && typeof(labels_processed[i][2]) == 'string') ? labels_processed[i][2] : 'white'); |
---|
1414 | context.fill(); |
---|
1415 | } |
---|
1416 | |
---|
1417 | i++; |
---|
1418 | } |
---|
1419 | } |
---|
1420 | } |
---|
1421 | } |
---|
1422 | |
---|
1423 | |
---|
1424 | /** |
---|
1425 | * This function makes it much easier to get the (if any) point that is currently being hovered over. |
---|
1426 | * |
---|
1427 | * @param object e The event object |
---|
1428 | */ |
---|
1429 | RGraph.Scatter.prototype.getPoint = function (e) |
---|
1430 | { |
---|
1431 | var canvas = e.target; |
---|
1432 | var obj = canvas.__object__; |
---|
1433 | var context = obj.context; |
---|
1434 | var context = obj.context; |
---|
1435 | var mouseXY = RGraph.getMouseXY(e); |
---|
1436 | var mouseX = mouseXY[0]; |
---|
1437 | var mouseY = mouseXY[1]; |
---|
1438 | var overHotspot = false; |
---|
1439 | var offset = obj.Get('chart.tooltips.hotspot'); // This is how far the hotspot extends |
---|
1440 | |
---|
1441 | for (var set=0; set<obj.coords.length; ++set) { |
---|
1442 | for (var i=0; i<obj.coords[set].length; ++i) { |
---|
1443 | |
---|
1444 | var xCoord = obj.coords[set][i][0]; |
---|
1445 | var yCoord = obj.coords[set][i][1]; |
---|
1446 | |
---|
1447 | if (mouseX <= (xCoord + offset) && |
---|
1448 | mouseX >= (xCoord - offset) && |
---|
1449 | mouseY <= (yCoord + offset) && |
---|
1450 | mouseY >= (yCoord - offset)) { |
---|
1451 | |
---|
1452 | return [xCoord, yCoord, set, i, obj.data[set][i][3]]; |
---|
1453 | } |
---|
1454 | } |
---|
1455 | } |
---|
1456 | } |
---|
1457 | |
---|
1458 | |
---|
1459 | /** |
---|
1460 | * Draws the above line labels |
---|
1461 | */ |
---|
1462 | RGraph.Scatter.prototype.DrawAboveLabels = function () |
---|
1463 | { |
---|
1464 | var context = this.context; |
---|
1465 | var size = this.Get('chart.labels.above.size'); |
---|
1466 | var font = this.Get('chart.text.font'); |
---|
1467 | var units_pre = this.Get('chart.units.pre'); |
---|
1468 | var units_post = this.Get('chart.units.post'); |
---|
1469 | |
---|
1470 | |
---|
1471 | for (var set=0; set<this.coords.length; ++set) { |
---|
1472 | for (var point=0; point<this.coords[set].length; ++point) { |
---|
1473 | |
---|
1474 | var x_val = this.data[set][point][0]; |
---|
1475 | var y_val = this.data[set][point][1]; |
---|
1476 | |
---|
1477 | |
---|
1478 | var x_pos = this.coords[set][point][0]; |
---|
1479 | var y_pos = this.coords[set][point][1]; |
---|
1480 | |
---|
1481 | RGraph.Text(context, |
---|
1482 | font, |
---|
1483 | size, |
---|
1484 | x_pos, |
---|
1485 | y_pos - 5 - size, |
---|
1486 | x_val.toFixed(this.Get('chart.labels.above.decimals')) + ', ' + y_val.toFixed(this.Get('chart.labels.above.decimals')), |
---|
1487 | 'center', |
---|
1488 | 'center', |
---|
1489 | true, |
---|
1490 | null, |
---|
1491 | 'rgba(255, 255, 255, 0.7)'); |
---|
1492 | } |
---|
1493 | } |
---|
1494 | } |
---|