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 bar chart constructor |
---|
19 | * |
---|
20 | * @param object canvas The canvas object |
---|
21 | * @param array data The chart data |
---|
22 | */ |
---|
23 | RGraph.Bar = function (id, data) |
---|
24 | { |
---|
25 | // Get the canvas and context objects |
---|
26 | this.id = id; |
---|
27 | this.canvas = document.getElementById(id); |
---|
28 | this.context = this.canvas.getContext ? this.canvas.getContext("2d") : null; |
---|
29 | this.canvas.__object__ = this; |
---|
30 | this.type = 'bar'; |
---|
31 | this.max = 0; |
---|
32 | this.stackedOrGrouped = false; |
---|
33 | this.isRGraph = true; |
---|
34 | |
---|
35 | /** |
---|
36 | * Compatibility with older browsers |
---|
37 | */ |
---|
38 | RGraph.OldBrowserCompat(this.context); |
---|
39 | |
---|
40 | |
---|
41 | // Various config type stuff |
---|
42 | this.properties = { |
---|
43 | 'chart.width': null, |
---|
44 | 'chart.height': null, |
---|
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.color': '#ddd', |
---|
49 | 'chart.background.grid.width': 1, |
---|
50 | 'chart.background.grid.hsize': 20, |
---|
51 | 'chart.background.grid.vsize': 20, |
---|
52 | 'chart.background.grid.vlines': true, |
---|
53 | 'chart.background.grid.hlines': true, |
---|
54 | 'chart.background.grid.border': true, |
---|
55 | 'chart.background.grid.autofit':false, |
---|
56 | 'chart.background.grid.autofit.numhlines': 7, |
---|
57 | 'chart.background.grid.autofit.numvlines': 20, |
---|
58 | 'chart.background.image': null, |
---|
59 | 'chart.ytickgap': 20, |
---|
60 | 'chart.smallyticks': 3, |
---|
61 | 'chart.largeyticks': 5, |
---|
62 | 'chart.numyticks': 10, |
---|
63 | 'chart.hmargin': 5, |
---|
64 | 'chart.strokecolor': '#666', |
---|
65 | 'chart.axis.color': 'black', |
---|
66 | 'chart.gutter.top': 25, |
---|
67 | 'chart.gutter.bottom': 25, |
---|
68 | 'chart.gutter.left': 25, |
---|
69 | 'chart.gutter.right': 25, |
---|
70 | 'chart.labels': null, |
---|
71 | 'chart.labels.ingraph': null, |
---|
72 | 'chart.labels.above': false, |
---|
73 | 'chart.labels.above.decimals': 0, |
---|
74 | 'chart.labels.above.size': null, |
---|
75 | 'chart.labels.above.angle': null, |
---|
76 | 'chart.ylabels': true, |
---|
77 | 'chart.ylabels.count': 5, |
---|
78 | 'chart.ylabels.inside': false, |
---|
79 | 'chart.xlabels.offset': 0, |
---|
80 | 'chart.xaxispos': 'bottom', |
---|
81 | 'chart.yaxispos': 'left', |
---|
82 | 'chart.text.color': 'black', |
---|
83 | 'chart.text.size': 10, |
---|
84 | 'chart.text.angle': 0, |
---|
85 | 'chart.text.font': 'Verdana', |
---|
86 | 'chart.ymax': null, |
---|
87 | 'chart.title': '', |
---|
88 | 'chart.title.background': null, |
---|
89 | 'chart.title.hpos': null, |
---|
90 | 'chart.title.vpos': null, |
---|
91 | 'chart.title.xaxis': '', |
---|
92 | 'chart.title.yaxis': '', |
---|
93 | 'chart.title.xaxis.pos': 0.25, |
---|
94 | 'chart.title.yaxis.pos': 0.25, |
---|
95 | 'chart.colors': ['rgb(0,0,255)', '#0f0', '#00f', '#ff0', '#0ff', '#0f0'], |
---|
96 | 'chart.colors.sequential': false, |
---|
97 | 'chart.colors.reverse': false, |
---|
98 | 'chart.grouping': 'grouped', |
---|
99 | 'chart.variant': 'bar', |
---|
100 | 'chart.shadow': false, |
---|
101 | 'chart.shadow.color': '#666', |
---|
102 | 'chart.shadow.offsetx': 3, |
---|
103 | 'chart.shadow.offsety': 3, |
---|
104 | 'chart.shadow.blur': 3, |
---|
105 | 'chart.tooltips': null, |
---|
106 | 'chart.tooltips.effect': 'fade', |
---|
107 | 'chart.tooltips.css.class': 'RGraph_tooltip', |
---|
108 | 'chart.tooltips.event': 'onclick', |
---|
109 | 'chart.tooltips.highlight': true, |
---|
110 | 'chart.highlight.stroke': 'black', |
---|
111 | 'chart.highlight.fill': 'rgba(255,255,255,0.5)', |
---|
112 | 'chart.background.hbars': null, |
---|
113 | 'chart.key': [], |
---|
114 | 'chart.key.background': 'white', |
---|
115 | 'chart.key.position': 'graph', |
---|
116 | 'chart.key.shadow': false, |
---|
117 | 'chart.key.shadow.color': '#666', |
---|
118 | 'chart.key.shadow.blur': 3, |
---|
119 | 'chart.key.shadow.offsetx': 2, |
---|
120 | 'chart.key.shadow.offsety': 2, |
---|
121 | 'chart.key.position.gutter.boxed': true, |
---|
122 | 'chart.key.position.x': null, |
---|
123 | 'chart.key.position.y': null, |
---|
124 | 'chart.key.halign': 'right', |
---|
125 | 'chart.key.color.shape': 'square', |
---|
126 | 'chart.key.rounded': true, |
---|
127 | 'chart.key.text.size': 10, |
---|
128 | 'chart.key.linewidth': 1, |
---|
129 | 'chart.contextmenu': null, |
---|
130 | 'chart.line': null, |
---|
131 | 'chart.units.pre': '', |
---|
132 | 'chart.units.post': '', |
---|
133 | 'chart.scale.decimals': 0, |
---|
134 | 'chart.scale.point': '.', |
---|
135 | 'chart.scale.thousand': ',', |
---|
136 | 'chart.crosshairs': false, |
---|
137 | 'chart.crosshairs.color': '#333', |
---|
138 | 'chart.linewidth': 1, |
---|
139 | 'chart.annotatable': false, |
---|
140 | 'chart.annotate.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.resizable': false, |
---|
154 | 'chart.resize.handle.adjust': [0,0], |
---|
155 | 'chart.resize.handle.background': null, |
---|
156 | 'chart.adjustable': false, |
---|
157 | 'chart.noaxes': false, |
---|
158 | 'chart.noxaxis': false, |
---|
159 | 'chart.noyaxis': false |
---|
160 | } |
---|
161 | |
---|
162 | // Check for support |
---|
163 | if (!this.canvas) { |
---|
164 | alert('[BAR] No canvas support'); |
---|
165 | return; |
---|
166 | } |
---|
167 | |
---|
168 | /** |
---|
169 | * Determine whether the chart will contain stacked or grouped bars |
---|
170 | */ |
---|
171 | for (i=0; i<data.length; ++i) { |
---|
172 | if (typeof(data[i]) == 'object') { |
---|
173 | this.stackedOrGrouped = true; |
---|
174 | } |
---|
175 | } |
---|
176 | |
---|
177 | // Store the data |
---|
178 | this.data = data; |
---|
179 | |
---|
180 | // Used to store the coords of the bars |
---|
181 | this.coords = []; |
---|
182 | |
---|
183 | /** |
---|
184 | * Set the .getShape commonly named method |
---|
185 | */ |
---|
186 | this.getShape = this.getBar; |
---|
187 | } |
---|
188 | |
---|
189 | |
---|
190 | /** |
---|
191 | * A setter |
---|
192 | * |
---|
193 | * @param name string The name of the property to set |
---|
194 | * @param value mixed The value of the property |
---|
195 | */ |
---|
196 | RGraph.Bar.prototype.Set = function (name, value) |
---|
197 | { |
---|
198 | name = name.toLowerCase(); |
---|
199 | |
---|
200 | if (name == 'chart.labels.abovebar') { |
---|
201 | name = 'chart.labels.above'; |
---|
202 | } |
---|
203 | |
---|
204 | if (name == 'chart.strokestyle') { |
---|
205 | name = 'chart.strokecolor'; |
---|
206 | } |
---|
207 | |
---|
208 | /** |
---|
209 | * Check for xaxispos |
---|
210 | */ |
---|
211 | if (name == 'chart.xaxispos' ) { |
---|
212 | if (value != 'bottom' && value != 'center' && value != 'top') { |
---|
213 | alert('[BAR] (' + this.id + ') chart.xaxispos should be top, center or bottom. Tried to set it to: ' + value + ' Changing it to center'); |
---|
214 | value = 'center'; |
---|
215 | } |
---|
216 | |
---|
217 | if (value == 'top') { |
---|
218 | for (var i=0; i<this.data.length; ++i) { |
---|
219 | if (typeof(this.data[i]) == 'number' && this.data[i] > 0) { |
---|
220 | alert('[BAR] The data element with index ' + i + ' should be negative'); |
---|
221 | } |
---|
222 | } |
---|
223 | } |
---|
224 | } |
---|
225 | |
---|
226 | this.properties[name] = value; |
---|
227 | } |
---|
228 | |
---|
229 | |
---|
230 | /** |
---|
231 | * A getter |
---|
232 | * |
---|
233 | * @param name string The name of the property to get |
---|
234 | */ |
---|
235 | RGraph.Bar.prototype.Get = function (name) |
---|
236 | { |
---|
237 | if (name == 'chart.labels.abovebar') { |
---|
238 | name = 'chart.labels.above'; |
---|
239 | } |
---|
240 | |
---|
241 | var value = this.properties[name]; |
---|
242 | |
---|
243 | return value; |
---|
244 | } |
---|
245 | |
---|
246 | |
---|
247 | /** |
---|
248 | * The function you call to draw the bar chart |
---|
249 | */ |
---|
250 | RGraph.Bar.prototype.Draw = function () |
---|
251 | { |
---|
252 | // MUST be the first thing done! |
---|
253 | if (typeof(this.Get('chart.background.image')) == 'string' && !this.__background_image__) { |
---|
254 | RGraph.DrawBackgroundImage(this); |
---|
255 | return; |
---|
256 | } |
---|
257 | |
---|
258 | /** |
---|
259 | * Fire the onbeforedraw event |
---|
260 | */ |
---|
261 | RGraph.FireCustomEvent(this, 'onbeforedraw'); |
---|
262 | |
---|
263 | /** |
---|
264 | * Clear all of this canvases event handlers (the ones installed by RGraph) |
---|
265 | */ |
---|
266 | RGraph.ClearEventListeners(this.id); |
---|
267 | |
---|
268 | /** |
---|
269 | * This is new in May 2011 and facilitates indiviual gutter settings, |
---|
270 | * eg chart.gutter.left |
---|
271 | */ |
---|
272 | this.gutterLeft = this.Get('chart.gutter.left'); |
---|
273 | this.gutterRight = this.Get('chart.gutter.right'); |
---|
274 | this.gutterTop = this.Get('chart.gutter.top'); |
---|
275 | this.gutterBottom = this.Get('chart.gutter.bottom'); |
---|
276 | |
---|
277 | /** |
---|
278 | * Convert any null values to 0. Won't make any difference to the bar (as opposed to the line chart) |
---|
279 | */ |
---|
280 | for (var i=0; i<this.data.length; ++i) { |
---|
281 | if (this.data[i] == null) { |
---|
282 | this.data[i] = 0; |
---|
283 | } |
---|
284 | } |
---|
285 | |
---|
286 | |
---|
287 | // Cache this in a class variable as it's used rather a lot |
---|
288 | |
---|
289 | /** |
---|
290 | * Check for tooltips and alert the user that they're not supported with pyramid charts |
---|
291 | */ |
---|
292 | if ( (this.Get('chart.variant') == 'pyramid' || this.Get('chart.variant') == 'dot') |
---|
293 | && typeof(this.Get('chart.tooltips')) == 'object' |
---|
294 | && this.Get('chart.tooltips') |
---|
295 | && this.Get('chart.tooltips').length > 0) { |
---|
296 | |
---|
297 | alert('[BAR] (' + this.id + ') Sorry, tooltips are not supported with dot or pyramid charts'); |
---|
298 | } |
---|
299 | |
---|
300 | /** |
---|
301 | * Stop the coords array from growing uncontrollably |
---|
302 | */ |
---|
303 | this.coords = []; |
---|
304 | |
---|
305 | /** |
---|
306 | * Work out a few things. They need to be here because they depend on things you can change before you |
---|
307 | * call Draw() but after you instantiate the object |
---|
308 | */ |
---|
309 | this.max = 0; |
---|
310 | this.grapharea = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
311 | this.halfgrapharea = this.grapharea / 2; |
---|
312 | this.halfTextHeight = this.Get('chart.text.size') / 2; |
---|
313 | |
---|
314 | // Progressively Draw the chart |
---|
315 | RGraph.background.Draw(this); |
---|
316 | |
---|
317 | |
---|
318 | //If it's a sketch chart variant, draw the axes first |
---|
319 | if (this.Get('chart.variant') == 'sketch') { |
---|
320 | this.DrawAxes(); |
---|
321 | this.Drawbars(); |
---|
322 | } else { |
---|
323 | this.Drawbars(); |
---|
324 | this.DrawAxes(); |
---|
325 | } |
---|
326 | |
---|
327 | this.DrawLabels(); |
---|
328 | |
---|
329 | |
---|
330 | // Draw the key if necessary |
---|
331 | if (this.Get('chart.key').length) { |
---|
332 | RGraph.DrawKey(this, this.Get('chart.key'), this.Get('chart.colors')); |
---|
333 | } |
---|
334 | |
---|
335 | |
---|
336 | /** |
---|
337 | * Setup the context menu if required |
---|
338 | */ |
---|
339 | if (this.Get('chart.contextmenu')) { |
---|
340 | RGraph.ShowContext(this); |
---|
341 | } |
---|
342 | |
---|
343 | |
---|
344 | /** |
---|
345 | * Is a line is defined, draw it |
---|
346 | */ |
---|
347 | var line = this.Get('chart.line'); |
---|
348 | |
---|
349 | if (line) { |
---|
350 | |
---|
351 | line.__bar__ = this; |
---|
352 | |
---|
353 | // Check the X axis positions |
---|
354 | if (this.Get('chart.xaxispos') != line.Get('chart.xaxispos')) { |
---|
355 | alert("[BAR] Using different X axis positions when combining the Bar and Line is not advised"); |
---|
356 | } |
---|
357 | |
---|
358 | line.Set('chart.gutter.left', this.Get('chart.gutter.left')); |
---|
359 | line.Set('chart.gutter.right', this.Get('chart.gutter.right')); |
---|
360 | line.Set('chart.gutter.top', this.Get('chart.gutter.top')); |
---|
361 | line.Set('chart.gutter.bottom', this.Get('chart.gutter.bottom')); |
---|
362 | |
---|
363 | line.Set('chart.hmargin', (this.canvas.width - this.gutterLeft - this.gutterRight) / (line.original_data[0].length * 2)); |
---|
364 | |
---|
365 | // If a BAR custom yMax is set, use that |
---|
366 | if (this.Get('chart.ymax') && !line.Get('chart.ymax')) { |
---|
367 | line.Set('chart.ymax', this.Get('chart.ymax')); |
---|
368 | |
---|
369 | } else if (line.Get('chart.ymax')) { |
---|
370 | line.Set('chart.ymax', line.Get('chart.ymax')); |
---|
371 | } |
---|
372 | |
---|
373 | line.Draw(); |
---|
374 | } |
---|
375 | |
---|
376 | |
---|
377 | /** |
---|
378 | * Draw "in graph" labels |
---|
379 | */ |
---|
380 | if (this.Get('chart.labels.ingraph')) { |
---|
381 | RGraph.DrawInGraphLabels(this); |
---|
382 | } |
---|
383 | |
---|
384 | /** |
---|
385 | * Draw crosschairs |
---|
386 | */ |
---|
387 | if (this.Get('chart.crosshairs')) { |
---|
388 | RGraph.DrawCrosshairs(this); |
---|
389 | } |
---|
390 | |
---|
391 | /** |
---|
392 | * If the canvas is annotatable, do install the event handlers |
---|
393 | */ |
---|
394 | if (this.Get('chart.annotatable')) { |
---|
395 | RGraph.Annotate(this); |
---|
396 | } |
---|
397 | |
---|
398 | /** |
---|
399 | * This bit shows the mini zoom window if requested |
---|
400 | */ |
---|
401 | if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { |
---|
402 | RGraph.ShowZoomWindow(this); |
---|
403 | } |
---|
404 | |
---|
405 | |
---|
406 | /** |
---|
407 | * This function enables resizing |
---|
408 | */ |
---|
409 | if (this.Get('chart.resizable')) { |
---|
410 | RGraph.AllowResizing(this); |
---|
411 | } |
---|
412 | |
---|
413 | |
---|
414 | /** |
---|
415 | * This function enables adjusting |
---|
416 | */ |
---|
417 | if (this.Get('chart.adjustable')) { |
---|
418 | RGraph.AllowAdjusting(this); |
---|
419 | } |
---|
420 | |
---|
421 | /** |
---|
422 | * Fire the RGraph ondraw event |
---|
423 | */ |
---|
424 | RGraph.FireCustomEvent(this, 'ondraw'); |
---|
425 | } |
---|
426 | |
---|
427 | |
---|
428 | /** |
---|
429 | * Draws the charts axes |
---|
430 | */ |
---|
431 | RGraph.Bar.prototype.DrawAxes = function () |
---|
432 | { |
---|
433 | if (this.Get('chart.noaxes')) { |
---|
434 | return; |
---|
435 | } |
---|
436 | |
---|
437 | var xaxispos = this.Get('chart.xaxispos'); |
---|
438 | var yaxispos = this.Get('chart.yaxispos'); |
---|
439 | |
---|
440 | this.context.beginPath(); |
---|
441 | this.context.strokeStyle = this.Get('chart.axis.color'); |
---|
442 | this.context.lineWidth = 1; |
---|
443 | |
---|
444 | // Draw the Y axis |
---|
445 | if (this.Get('chart.noyaxis') == false) { |
---|
446 | if (yaxispos == 'right') { |
---|
447 | this.context.moveTo(RGraph.GetWidth(this) - this.gutterRight, this.gutterTop); |
---|
448 | this.context.lineTo(RGraph.GetWidth(this) - this.gutterRight, RGraph.GetHeight(this) - this.gutterBottom); |
---|
449 | } else { |
---|
450 | this.context.moveTo(this.gutterLeft, this.gutterTop); |
---|
451 | this.context.lineTo(this.gutterLeft, RGraph.GetHeight(this) - this.gutterBottom); |
---|
452 | } |
---|
453 | } |
---|
454 | |
---|
455 | // Draw the X axis |
---|
456 | if (this.Get('chart.noxaxis') == false) { |
---|
457 | if (xaxispos == 'center') { |
---|
458 | this.context.moveTo(this.gutterLeft, ((this.canvas.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop); |
---|
459 | this.context.lineTo(this.canvas.width - this.gutterRight, ((this.canvas.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop); |
---|
460 | } else if (xaxispos == 'top') { |
---|
461 | this.context.moveTo(this.gutterLeft, this.gutterTop); |
---|
462 | this.context.lineTo(this.canvas.width - this.gutterRight, this.gutterTop); |
---|
463 | } else { |
---|
464 | this.context.moveTo(this.gutterLeft, RGraph.GetHeight(this) - this.gutterBottom); |
---|
465 | this.context.lineTo(RGraph.GetWidth(this) - this.gutterRight, RGraph.GetHeight(this) - this.gutterBottom); |
---|
466 | } |
---|
467 | } |
---|
468 | |
---|
469 | var numYTicks = this.Get('chart.numyticks'); |
---|
470 | |
---|
471 | // Draw the Y tickmarks |
---|
472 | if (this.Get('chart.noyaxis') == false) { |
---|
473 | var yTickGap = (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom) / numYTicks; |
---|
474 | var xpos = yaxispos == 'left' ? this.gutterLeft : RGraph.GetWidth(this) - this.gutterRight; |
---|
475 | |
---|
476 | for (y=this.gutterTop; |
---|
477 | xaxispos == 'center' ? y <= (RGraph.GetHeight(this) - this.gutterBottom) : y < (RGraph.GetHeight(this) - this.gutterBottom + (xaxispos == 'top' ? 1 : 0)); |
---|
478 | y += yTickGap) { |
---|
479 | |
---|
480 | if (xaxispos == 'center' && y == (RGraph.GetHeight(this) / 2)) continue; |
---|
481 | |
---|
482 | // X axis at the top |
---|
483 | if (xaxispos == 'top' && y == this.gutterTop) continue; |
---|
484 | |
---|
485 | this.context.moveTo(xpos, y); |
---|
486 | this.context.lineTo(xpos + (yaxispos == 'left' ? -3 : 3), y); |
---|
487 | } |
---|
488 | |
---|
489 | /** |
---|
490 | * If the X axis is not being shown, draw an extra tick |
---|
491 | */ |
---|
492 | if (this.Get('chart.noxaxis')) { |
---|
493 | if (xaxispos == 'center') { |
---|
494 | this.context.moveTo(xpos + (yaxispos == 'left' ? -3 : 3), RGraph.GetHeight(this) / 2); |
---|
495 | this.context.lineTo(xpos, RGraph.GetHeight(this) / 2); |
---|
496 | } else if (xaxispos == 'top') { |
---|
497 | this.context.moveTo(xpos + (yaxispos == 'left' ? -3 : 3), this.gutterTop); |
---|
498 | this.context.lineTo(xpos, this.gutterTop); |
---|
499 | } else { |
---|
500 | this.context.moveTo(xpos + (yaxispos == 'left' ? -3 : 3), RGraph.GetHeight(this) - this.gutterBottom); |
---|
501 | this.context.lineTo(xpos, RGraph.GetHeight(this) - this.gutterBottom); |
---|
502 | } |
---|
503 | } |
---|
504 | } |
---|
505 | |
---|
506 | |
---|
507 | // Draw the X tickmarks |
---|
508 | if (this.Get('chart.noxaxis') == false) { |
---|
509 | |
---|
510 | xTickGap = (RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight) / this.data.length; |
---|
511 | |
---|
512 | if (xaxispos == 'bottom') { |
---|
513 | yStart = this.canvas.height - this.gutterBottom; |
---|
514 | yEnd = (this.canvas.height - this.gutterBottom) + 3; |
---|
515 | } else if (xaxispos == 'top') { |
---|
516 | yStart = this.gutterTop - 3; |
---|
517 | yEnd = this.gutterTop; |
---|
518 | } else if (xaxispos == 'center') { |
---|
519 | yStart = ((this.canvas.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop + 3; |
---|
520 | yEnd = ((this.canvas.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop - 3; |
---|
521 | } |
---|
522 | |
---|
523 | //////////////// X TICKS //////////////// |
---|
524 | |
---|
525 | var noEndXTick = this.Get('chart.noendxtick'); |
---|
526 | |
---|
527 | for (x=this.gutterLeft + (yaxispos == 'left' ? xTickGap : 0); x<this.canvas.width - this.gutterRight + (yaxispos == 'left' ? 5 : 0); x+=xTickGap) { |
---|
528 | |
---|
529 | if (yaxispos == 'left' && !noEndXTick && x > this.gutterLeft) { |
---|
530 | this.context.moveTo(x, yStart); |
---|
531 | this.context.lineTo(x, yEnd); |
---|
532 | |
---|
533 | } else if (yaxispos == 'left' && noEndXTick && x > this.gutterLeft && x < (this.canvas.width - this.gutterRight) ) { |
---|
534 | this.context.moveTo(x, yStart); |
---|
535 | this.context.lineTo(x, yEnd); |
---|
536 | |
---|
537 | } else if (yaxispos == 'right' && x < (this.canvas.width - this.gutterRight) && !noEndXTick) { |
---|
538 | this.context.moveTo(x, yStart); |
---|
539 | this.context.lineTo(x, yEnd); |
---|
540 | |
---|
541 | } else if (yaxispos == 'right' && x < (this.canvas.width - this.gutterRight) && x > (this.gutterLeft) && noEndXTick) { |
---|
542 | this.context.moveTo(x, yStart); |
---|
543 | this.context.lineTo(x, yEnd); |
---|
544 | } |
---|
545 | } |
---|
546 | |
---|
547 | if (this.Get('chart.noyaxis')) { |
---|
548 | this.context.moveTo(this.gutterLeft, yStart); |
---|
549 | this.context.lineTo(this.gutterLeft, yEnd); |
---|
550 | } |
---|
551 | |
---|
552 | //////////////// X TICKS //////////////// |
---|
553 | } |
---|
554 | |
---|
555 | /** |
---|
556 | * If the Y axis is not being shown, draw an extra tick |
---|
557 | */ |
---|
558 | if (this.Get('chart.noyaxis') && this.Get('chart.noxaxis') == false) { |
---|
559 | if (xaxispos == 'center') { |
---|
560 | this.context.moveTo(this.gutterLeft, (RGraph.GetHeight(this) / 2) - 3); |
---|
561 | this.context.lineTo(this.gutterLeft, (RGraph.GetHeight(this) / 2) + 3); |
---|
562 | } else { |
---|
563 | this.context.moveTo(this.gutterLeft, this.canvas.height - this.gutterBottom); |
---|
564 | this.context.lineTo(this.gutterLeft, this.canvas.height - this.gutterBottom + 3); |
---|
565 | } |
---|
566 | } |
---|
567 | |
---|
568 | this.context.stroke(); |
---|
569 | } |
---|
570 | |
---|
571 | |
---|
572 | /** |
---|
573 | * Draws the bars |
---|
574 | */ |
---|
575 | RGraph.Bar.prototype.Drawbars = function () |
---|
576 | { |
---|
577 | this.context.lineWidth = this.Get('chart.linewidth'); |
---|
578 | this.context.strokeStyle = this.Get('chart.strokecolor'); |
---|
579 | this.context.fillStyle = this.Get('chart.colors')[0]; |
---|
580 | var prevX = 0; |
---|
581 | var prevY = 0; |
---|
582 | var decimals = this.Get('chart.scale.decimals'); |
---|
583 | |
---|
584 | /** |
---|
585 | * Work out the max value |
---|
586 | */ |
---|
587 | if (this.Get('chart.ymax')) { |
---|
588 | this.max = this.Get('chart.ymax'); |
---|
589 | |
---|
590 | this.scale = [ |
---|
591 | (this.max * (1/5)).toFixed(decimals), |
---|
592 | (this.max * (2/5)).toFixed(decimals), |
---|
593 | (this.max * (3/5)).toFixed(decimals), |
---|
594 | (this.max * (4/5)).toFixed(decimals), |
---|
595 | this.max.toFixed(decimals) |
---|
596 | ]; |
---|
597 | } else { |
---|
598 | for (i=0; i<this.data.length; ++i) { |
---|
599 | if (typeof(this.data[i]) == 'object') { |
---|
600 | var value = this.Get('chart.grouping') == 'grouped' ? Number(RGraph.array_max(this.data[i], true)) : Number(RGraph.array_sum(this.data[i])) ; |
---|
601 | |
---|
602 | } else { |
---|
603 | var value = Number(this.data[i]); |
---|
604 | } |
---|
605 | |
---|
606 | this.max = Math.max(Math.abs(this.max), Math.abs(value)); |
---|
607 | } |
---|
608 | |
---|
609 | this.scale = RGraph.getScale(this.max, this); |
---|
610 | this.max = this.scale[4]; |
---|
611 | |
---|
612 | if (this.Get('chart.scale.decimals')) { |
---|
613 | var decimals = this.Get('chart.scale.decimals'); |
---|
614 | |
---|
615 | this.scale[0] = Number(this.scale[0]).toFixed(decimals); |
---|
616 | this.scale[1] = Number(this.scale[1]).toFixed(decimals); |
---|
617 | this.scale[2] = Number(this.scale[2]).toFixed(decimals); |
---|
618 | this.scale[3] = Number(this.scale[3]).toFixed(decimals); |
---|
619 | this.scale[4] = Number(this.scale[4]).toFixed(decimals); |
---|
620 | } |
---|
621 | } |
---|
622 | |
---|
623 | /** |
---|
624 | * Draw horizontal bars here |
---|
625 | */ |
---|
626 | if (this.Get('chart.background.hbars') && this.Get('chart.background.hbars').length > 0) { |
---|
627 | RGraph.DrawBars(this); |
---|
628 | } |
---|
629 | |
---|
630 | var variant = this.Get('chart.variant'); |
---|
631 | |
---|
632 | /** |
---|
633 | * Draw the 3D axes is necessary |
---|
634 | */ |
---|
635 | if (variant == '3d') { |
---|
636 | RGraph.Draw3DAxes(this); |
---|
637 | } |
---|
638 | |
---|
639 | /** |
---|
640 | * Get the variant once, and draw the bars, be they regular, stacked or grouped |
---|
641 | */ |
---|
642 | |
---|
643 | // Get these variables outside of the loop |
---|
644 | var xaxispos = this.Get('chart.xaxispos'); |
---|
645 | var width = (RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight ) / this.data.length; |
---|
646 | var orig_height = height; |
---|
647 | var hmargin = this.Get('chart.hmargin'); |
---|
648 | var shadow = this.Get('chart.shadow'); |
---|
649 | var shadowColor = this.Get('chart.shadow.color'); |
---|
650 | var shadowBlur = this.Get('chart.shadow.blur'); |
---|
651 | var shadowOffsetX = this.Get('chart.shadow.offsetx'); |
---|
652 | var shadowOffsetY = this.Get('chart.shadow.offsety'); |
---|
653 | var strokeStyle = this.Get('chart.strokecolor'); |
---|
654 | var colors = this.Get('chart.colors'); |
---|
655 | |
---|
656 | for (i=0; i<this.data.length; ++i) { |
---|
657 | |
---|
658 | // Work out the height |
---|
659 | //The width is up outside the loop |
---|
660 | var height = (RGraph.array_sum(this.data[i]) / this.max) * (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom); |
---|
661 | |
---|
662 | // Half the height if the Y axis is at the center |
---|
663 | if (xaxispos == 'center') { |
---|
664 | height /= 2; |
---|
665 | } |
---|
666 | |
---|
667 | var x = (i * width) + this.gutterLeft; |
---|
668 | var y = xaxispos == 'center' ? ((this.canvas.height - this.gutterTop - this.gutterBottom) / 2) + this.gutterTop - height : RGraph.GetHeight(this) - height - this.gutterBottom; |
---|
669 | |
---|
670 | // xaxispos is top |
---|
671 | if (xaxispos == 'top') { |
---|
672 | y = this.gutterTop + Math.abs(height); |
---|
673 | } |
---|
674 | |
---|
675 | |
---|
676 | // Account for negative lengths - Some browsers (eg Chrome) don't like a negative value |
---|
677 | if (height < 0) { |
---|
678 | y += height; |
---|
679 | height = Math.abs(height); |
---|
680 | } |
---|
681 | |
---|
682 | /** |
---|
683 | * Turn on the shadow if need be |
---|
684 | */ |
---|
685 | if (shadow) { |
---|
686 | this.context.shadowColor = shadowColor; |
---|
687 | this.context.shadowBlur = shadowBlur; |
---|
688 | this.context.shadowOffsetX = shadowOffsetX; |
---|
689 | this.context.shadowOffsetY = shadowOffsetY; |
---|
690 | } |
---|
691 | |
---|
692 | /** |
---|
693 | * Draw the bar |
---|
694 | */ |
---|
695 | this.context.beginPath(); |
---|
696 | if (typeof(this.data[i]) == 'number') { |
---|
697 | |
---|
698 | var barWidth = width - (2 * hmargin); |
---|
699 | |
---|
700 | // Set the fill color |
---|
701 | this.context.strokeStyle = strokeStyle; |
---|
702 | this.context.fillStyle = colors[0]; |
---|
703 | |
---|
704 | /** |
---|
705 | * Sequential colors |
---|
706 | */ |
---|
707 | if (this.Get('chart.colors.sequential')) { |
---|
708 | this.context.fillStyle = colors[i]; |
---|
709 | } |
---|
710 | |
---|
711 | if (variant == 'sketch') { |
---|
712 | |
---|
713 | this.context.lineCap = 'round'; |
---|
714 | |
---|
715 | var sketchOffset = 3; |
---|
716 | |
---|
717 | this.context.beginPath(); |
---|
718 | |
---|
719 | this.context.strokeStyle = colors[0]; |
---|
720 | |
---|
721 | /** |
---|
722 | * Sequential colors |
---|
723 | */ |
---|
724 | if (this.Get('chart.colors.sequential')) { |
---|
725 | this.context.strokeStyle = colors[i]; |
---|
726 | } |
---|
727 | |
---|
728 | // Left side |
---|
729 | this.context.moveTo(x + hmargin + 2, y + height - 2); |
---|
730 | this.context.lineTo(x + hmargin , y - 2); |
---|
731 | |
---|
732 | // The top |
---|
733 | this.context.moveTo(x + hmargin - 3, y + -2 + (this.data[i] < 0 ? height : 0)); |
---|
734 | this.context.bezierCurveTo(x + ((hmargin + width) * 0.33),y + 5 + (this.data[i] < 0 ? height - 10: 0),x + ((hmargin + width) * 0.66),y + 5 + (this.data[i] < 0 ? height - 10 : 0),x + hmargin + width + -1, y + 0 + (this.data[i] < 0 ? height : 0)); |
---|
735 | |
---|
736 | |
---|
737 | // The right side |
---|
738 | this.context.moveTo(x + hmargin + width - 2, y + -2); |
---|
739 | this.context.lineTo(x + hmargin + width - 3, y + height - 3); |
---|
740 | |
---|
741 | for (var r=0.2; r<=0.8; r+=0.2) { |
---|
742 | this.context.moveTo(x + hmargin + width + (r > 0.4 ? -1 : 3) - (r * width),y - 1); |
---|
743 | this.context.lineTo(x + hmargin + width - (r > 0.4 ? 1 : -1) - (r * width), y + height + (r == 0.2 ? 1 : -2)); |
---|
744 | } |
---|
745 | |
---|
746 | this.context.stroke(); |
---|
747 | |
---|
748 | // Regular bar |
---|
749 | } else if (variant == 'bar' || variant == '3d' || variant == 'glass' || variant == 'bevel') { |
---|
750 | |
---|
751 | if (RGraph.isIE8() && shadow) { |
---|
752 | this.DrawIEShadow([x + hmargin, y, barWidth, height]); |
---|
753 | } |
---|
754 | |
---|
755 | if (variant == 'glass') { |
---|
756 | RGraph.filledCurvyRect(this.context, x + hmargin, y, barWidth, height, 3, this.data[i] > 0, this.data[i] > 0, this.data[i] < 0, this.data[i] < 0); |
---|
757 | RGraph.strokedCurvyRect(this.context, x + hmargin, y, barWidth, height, 3, this.data[i] > 0, this.data[i] > 0, this.data[i] < 0, this.data[i] < 0); |
---|
758 | } else { |
---|
759 | this.context.strokeRect(x + hmargin, y, barWidth, height); |
---|
760 | this.context.fillRect(x + hmargin, y, barWidth, height); |
---|
761 | } |
---|
762 | |
---|
763 | |
---|
764 | // This bit draws the text labels that appear above the bars if requested |
---|
765 | if (this.Get('chart.labels.above')) { |
---|
766 | |
---|
767 | // Turn off any shadow |
---|
768 | if (shadow) { |
---|
769 | RGraph.NoShadow(this); |
---|
770 | } |
---|
771 | |
---|
772 | var yPos = y - 3; |
---|
773 | |
---|
774 | // Account for negative bars |
---|
775 | if (this.data[i] < 0) { |
---|
776 | yPos += height + 6 + (this.Get('chart.text.size') - 4); |
---|
777 | } |
---|
778 | |
---|
779 | // Account for chart.xaxispos=top |
---|
780 | if (this.Get('chart.xaxispos') == 'top') { |
---|
781 | yPos = this.gutterTop + height + 6 + (typeof(this.Get('chart.labels.above.size')) == 'number' ? this.Get('chart.labels.above.size') : this.Get('chart.text.size') - 4); |
---|
782 | } |
---|
783 | |
---|
784 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
785 | |
---|
786 | RGraph.Text(this.context, |
---|
787 | this.Get('chart.text.font'), |
---|
788 | typeof(this.Get('chart.labels.above.size')) == 'number' ? this.Get('chart.labels.above.size') : this.Get('chart.text.size') - 3, |
---|
789 | x + hmargin + (barWidth / 2), |
---|
790 | yPos, |
---|
791 | RGraph.number_format(this, Number(this.data[i]).toFixed(this.Get('chart.labels.above.decimals')),this.Get('chart.units.pre'),this.Get('chart.units.post')), |
---|
792 | this.Get('chart.labels.above.angle') ? 'bottom' : null, |
---|
793 | this.Get('chart.labels.above.angle') ? (this.Get('chart.labels.above.angle') > 0 && (this.Get('chart.xaxispos') != 'top') ? 'right' : 'left') : 'center', |
---|
794 | null, |
---|
795 | this.Get('chart.labels.above.angle') |
---|
796 | ); |
---|
797 | } |
---|
798 | |
---|
799 | // 3D effect |
---|
800 | if (variant == '3d') { |
---|
801 | |
---|
802 | var prevStrokeStyle = this.context.strokeStyle; |
---|
803 | var prevFillStyle = this.context.fillStyle; |
---|
804 | |
---|
805 | // Draw the top |
---|
806 | this.context.beginPath(); |
---|
807 | this.context.moveTo(x + hmargin, y); |
---|
808 | this.context.lineTo(x + hmargin + 10, y - 5); |
---|
809 | this.context.lineTo(x + hmargin + 10 + barWidth, y - 5); |
---|
810 | this.context.lineTo(x + hmargin + barWidth, y); |
---|
811 | this.context.closePath(); |
---|
812 | |
---|
813 | this.context.stroke(); |
---|
814 | this.context.fill(); |
---|
815 | |
---|
816 | // Draw the right hand side |
---|
817 | this.context.beginPath(); |
---|
818 | this.context.moveTo(x + hmargin + barWidth, y); |
---|
819 | this.context.lineTo(x + hmargin + barWidth + 10, y - 5); |
---|
820 | this.context.lineTo(x + hmargin + barWidth + 10, y + height - 5); |
---|
821 | this.context.lineTo(x + hmargin + barWidth, y + height); |
---|
822 | this.context.closePath(); |
---|
823 | |
---|
824 | this.context.stroke(); |
---|
825 | this.context.fill(); |
---|
826 | |
---|
827 | // Draw the darker top section |
---|
828 | this.context.beginPath(); |
---|
829 | this.context.fillStyle = 'rgba(255,255,255,0.3)'; |
---|
830 | this.context.moveTo(x + hmargin, y); |
---|
831 | this.context.lineTo(x + hmargin + 10, y - 5); |
---|
832 | this.context.lineTo(x + hmargin + 10 + barWidth, y - 5); |
---|
833 | this.context.lineTo(x + hmargin + barWidth, y); |
---|
834 | this.context.lineTo(x + hmargin, y); |
---|
835 | this.context.closePath(); |
---|
836 | |
---|
837 | this.context.stroke(); |
---|
838 | this.context.fill(); |
---|
839 | |
---|
840 | // Draw the darker right side section |
---|
841 | this.context.beginPath(); |
---|
842 | this.context.fillStyle = 'rgba(0,0,0,0.4)'; |
---|
843 | this.context.moveTo(x + hmargin + barWidth, y); |
---|
844 | this.context.lineTo(x + hmargin + barWidth + 10, y - 5); |
---|
845 | this.context.lineTo(x + hmargin + barWidth + 10, y - 5 + height); |
---|
846 | this.context.lineTo(x + hmargin + barWidth, y + height); |
---|
847 | this.context.lineTo(x + hmargin + barWidth, y); |
---|
848 | this.context.closePath(); |
---|
849 | |
---|
850 | this.context.stroke(); |
---|
851 | this.context.fill(); |
---|
852 | |
---|
853 | this.context.strokeStyle = prevStrokeStyle; |
---|
854 | this.context.fillStyle = prevFillStyle; |
---|
855 | |
---|
856 | // Glass variant |
---|
857 | } else if (variant == 'glass') { |
---|
858 | |
---|
859 | var grad = this.context.createLinearGradient( |
---|
860 | x + hmargin, |
---|
861 | y, |
---|
862 | x + hmargin + (barWidth / 2), |
---|
863 | y |
---|
864 | ); |
---|
865 | grad.addColorStop(0, 'rgba(255,255,255,0.9)'); |
---|
866 | grad.addColorStop(1, 'rgba(255,255,255,0.5)'); |
---|
867 | |
---|
868 | this.context.beginPath(); |
---|
869 | this.context.fillStyle = grad; |
---|
870 | this.context.fillRect(x + hmargin + 2,y + (this.data[i] > 0 ? 2 : 0),(barWidth / 2) - 2,height - 2); |
---|
871 | this.context.fill(); |
---|
872 | } |
---|
873 | |
---|
874 | // Dot chart |
---|
875 | } else if (variant == 'dot') { |
---|
876 | |
---|
877 | this.context.beginPath(); |
---|
878 | this.context.moveTo(x + (width / 2), y); |
---|
879 | this.context.lineTo(x + (width / 2), y + height); |
---|
880 | this.context.stroke(); |
---|
881 | |
---|
882 | this.context.beginPath(); |
---|
883 | this.context.fillStyle = this.Get('chart.colors')[i]; |
---|
884 | this.context.arc(x + (width / 2), y + (this.data[i] > 0 ? 0 : height), 2, 0, 6.28, 0); |
---|
885 | |
---|
886 | // Set the colour for the dots |
---|
887 | this.context.fillStyle = this.Get('chart.colors')[0]; |
---|
888 | |
---|
889 | /** |
---|
890 | * Sequential colors |
---|
891 | */ |
---|
892 | if (this.Get('chart.colors.sequential')) { |
---|
893 | this.context.fillStyle = colors[i]; |
---|
894 | } |
---|
895 | |
---|
896 | this.context.stroke(); |
---|
897 | this.context.fill(); |
---|
898 | |
---|
899 | // Pyramid chart |
---|
900 | } else if (variant == 'pyramid') { |
---|
901 | |
---|
902 | this.context.beginPath(); |
---|
903 | var startY = (this.Get('chart.xaxispos') == 'center' ? (RGraph.GetHeight(this) / 2) : (RGraph.GetHeight(this) - this.gutterBottom)); |
---|
904 | |
---|
905 | this.context.moveTo(x + hmargin, startY); |
---|
906 | this.context.lineTo( |
---|
907 | x + hmargin + (barWidth / 2), |
---|
908 | y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0) |
---|
909 | ); |
---|
910 | this.context.lineTo(x + hmargin + barWidth, startY); |
---|
911 | |
---|
912 | this.context.closePath(); |
---|
913 | |
---|
914 | this.context.stroke(); |
---|
915 | this.context.fill(); |
---|
916 | |
---|
917 | // Arrow chart |
---|
918 | } else if (variant == 'arrow') { |
---|
919 | |
---|
920 | var startY = (this.Get('chart.xaxispos') == 'center' ? (RGraph.GetHeight(this) / 2) : (RGraph.GetHeight(this) - this.gutterBottom)); |
---|
921 | |
---|
922 | this.context.lineWidth = this.Get('chart.linewidth') ? this.Get('chart.linewidth') : 1; |
---|
923 | this.context.lineCap = 'round'; |
---|
924 | |
---|
925 | this.context.beginPath(); |
---|
926 | |
---|
927 | this.context.moveTo(x + hmargin + (barWidth / 2), startY); |
---|
928 | this.context.lineTo(x + hmargin + (barWidth / 2), y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0)); |
---|
929 | this.context.arc(x + hmargin + (barWidth / 2), |
---|
930 | y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0), |
---|
931 | 5, |
---|
932 | this.data[i] > 0 ? 0.78 : 5.6, |
---|
933 | this.data[i] > 0 ? 0.79 : 5.48, |
---|
934 | this.data[i] < 0); |
---|
935 | |
---|
936 | this.context.moveTo(x + hmargin + (barWidth / 2), y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0)); |
---|
937 | this.context.arc(x + hmargin + (barWidth / 2), |
---|
938 | y + (this.Get('chart.xaxispos') == 'center' && (this.data[i] < 0) ? height : 0), |
---|
939 | 5, |
---|
940 | this.data[i] > 0 ? 2.355 : 4, |
---|
941 | this.data[i] > 0 ? 2.4 : 3.925, |
---|
942 | this.data[i] < 0); |
---|
943 | |
---|
944 | this.context.stroke(); |
---|
945 | |
---|
946 | this.context.lineWidth = 1; |
---|
947 | |
---|
948 | // Unknown variant type |
---|
949 | } else { |
---|
950 | alert('[BAR] Warning! Unknown chart.variant: ' + variant); |
---|
951 | } |
---|
952 | |
---|
953 | this.coords.push([x + hmargin, y, width - (2 * hmargin), height]); |
---|
954 | |
---|
955 | |
---|
956 | /** |
---|
957 | * Stacked bar |
---|
958 | */ |
---|
959 | } else if (typeof(this.data[i]) == 'object' && this.Get('chart.grouping') == 'stacked') { |
---|
960 | |
---|
961 | var barWidth = width - (2 * hmargin); |
---|
962 | var redrawCoords = [];// Necessary to draw if the shadow is enabled |
---|
963 | var startY = 0; |
---|
964 | |
---|
965 | for (j=0; j<this.data[i].length; ++j) { |
---|
966 | |
---|
967 | // Stacked bar chart and X axis pos in the middle - poitless since negative values are not permitted |
---|
968 | if (xaxispos == 'center') { |
---|
969 | alert("[BAR] It's fruitless having the X axis position at the center on a stacked bar chart."); |
---|
970 | return; |
---|
971 | } |
---|
972 | |
---|
973 | // Negative values not permitted for the stacked chart |
---|
974 | if (this.data[i][j] < 0) { |
---|
975 | alert('[BAR] Negative values are not permitted with a stacked bar chart. Try a grouped one instead.'); |
---|
976 | return; |
---|
977 | } |
---|
978 | |
---|
979 | /** |
---|
980 | * Set the fill and stroke colors |
---|
981 | */ |
---|
982 | this.context.strokeStyle = strokeStyle |
---|
983 | this.context.fillStyle = colors[j]; |
---|
984 | |
---|
985 | if (this.Get('chart.colors.reverse')) { |
---|
986 | this.context.fillStyle = colors[this.data[i].length - j - 1]; |
---|
987 | } |
---|
988 | |
---|
989 | var height = (this.data[i][j] / this.max) * (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom ); |
---|
990 | |
---|
991 | // If the X axis pos is in the center, we need to half the height |
---|
992 | if (xaxispos == 'center') { |
---|
993 | height /= 2; |
---|
994 | } |
---|
995 | |
---|
996 | var totalHeight = (RGraph.array_sum(this.data[i]) / this.max) * (RGraph.GetHeight(this) - hmargin - this.gutterTop - this.gutterBottom); |
---|
997 | |
---|
998 | /** |
---|
999 | * Store the coords for tooltips |
---|
1000 | */ |
---|
1001 | this.coords.push([x + hmargin, y, width - (2 * hmargin), height]); |
---|
1002 | |
---|
1003 | // MSIE shadow |
---|
1004 | if (document.all && shadow) { |
---|
1005 | this.DrawIEShadow([x + hmargin, y, width - (2 * hmargin), height + 1]); |
---|
1006 | } |
---|
1007 | |
---|
1008 | this.context.strokeRect(x + hmargin, y, width - (2 * hmargin), height); |
---|
1009 | this.context.fillRect(x + hmargin, y, width - (2 * hmargin), height); |
---|
1010 | |
---|
1011 | |
---|
1012 | if (j == 0) { |
---|
1013 | var startY = y; |
---|
1014 | var startX = x; |
---|
1015 | } |
---|
1016 | |
---|
1017 | /** |
---|
1018 | * Store the redraw coords if the shadow is enabled |
---|
1019 | */ |
---|
1020 | if (shadow) { |
---|
1021 | redrawCoords.push([x + hmargin, y, width - (2 * hmargin), height, colors[j]]); |
---|
1022 | } |
---|
1023 | |
---|
1024 | /** |
---|
1025 | * Stacked 3D effect |
---|
1026 | */ |
---|
1027 | if (variant == '3d') { |
---|
1028 | |
---|
1029 | var prevFillStyle = this.context.fillStyle; |
---|
1030 | var prevStrokeStyle = this.context.strokeStyle; |
---|
1031 | |
---|
1032 | |
---|
1033 | // Draw the top side |
---|
1034 | if (j == 0) { |
---|
1035 | this.context.beginPath(); |
---|
1036 | this.context.moveTo(startX + hmargin, y); |
---|
1037 | this.context.lineTo(startX + 10 + hmargin, y - 5); |
---|
1038 | this.context.lineTo(startX + 10 + barWidth + hmargin, y - 5); |
---|
1039 | this.context.lineTo(startX + barWidth + hmargin, y); |
---|
1040 | this.context.closePath(); |
---|
1041 | |
---|
1042 | this.context.fill(); |
---|
1043 | this.context.stroke(); |
---|
1044 | } |
---|
1045 | |
---|
1046 | // Draw the side section |
---|
1047 | this.context.beginPath(); |
---|
1048 | this.context.moveTo(startX + barWidth + hmargin, y); |
---|
1049 | this.context.lineTo(startX + barWidth + hmargin + 10, y - 5); |
---|
1050 | this.context.lineTo(startX + barWidth + + hmargin + 10, y - 5 + height); |
---|
1051 | this.context.lineTo(startX + barWidth + hmargin , y + height); |
---|
1052 | this.context.closePath(); |
---|
1053 | |
---|
1054 | this.context.fill(); |
---|
1055 | this.context.stroke(); |
---|
1056 | |
---|
1057 | // Draw the darker top side |
---|
1058 | if (j == 0) { |
---|
1059 | this.context.fillStyle = 'rgba(255,255,255,0.3)'; |
---|
1060 | this.context.beginPath(); |
---|
1061 | this.context.moveTo(startX + hmargin, y); |
---|
1062 | this.context.lineTo(startX + 10 + hmargin, y - 5); |
---|
1063 | this.context.lineTo(startX + 10 + barWidth + hmargin, y - 5); |
---|
1064 | this.context.lineTo(startX + barWidth + hmargin, y); |
---|
1065 | this.context.closePath(); |
---|
1066 | |
---|
1067 | this.context.fill(); |
---|
1068 | this.context.stroke(); |
---|
1069 | } |
---|
1070 | |
---|
1071 | // Draw the darker side section |
---|
1072 | this.context.fillStyle = 'rgba(0,0,0,0.4)'; |
---|
1073 | this.context.beginPath(); |
---|
1074 | this.context.moveTo(startX + barWidth + hmargin, y); |
---|
1075 | this.context.lineTo(startX + barWidth + hmargin + 10, y - 5); |
---|
1076 | this.context.lineTo(startX + barWidth + + hmargin + 10, y - 5 + height); |
---|
1077 | this.context.lineTo(startX + barWidth + hmargin , y + height); |
---|
1078 | this.context.closePath(); |
---|
1079 | |
---|
1080 | this.context.fill(); |
---|
1081 | this.context.stroke(); |
---|
1082 | |
---|
1083 | this.context.strokeStyle = prevStrokeStyle; |
---|
1084 | this.context.fillStyle = prevFillStyle; |
---|
1085 | } |
---|
1086 | |
---|
1087 | y += height; |
---|
1088 | } |
---|
1089 | |
---|
1090 | // This bit draws the text labels that appear above the bars if requested |
---|
1091 | if (this.Get('chart.labels.above')) { |
---|
1092 | |
---|
1093 | // Turn off any shadow |
---|
1094 | RGraph.NoShadow(this); |
---|
1095 | |
---|
1096 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
1097 | RGraph.Text(this.context,this.Get('chart.text.font'),typeof(this.Get('chart.labels.above.size')) == 'number' ? this.Get('chart.labels.above.size') : this.Get('chart.text.size') - 3,startX + (barWidth / 2) + this.Get('chart.hmargin'),startY - (this.Get('chart.shadow') && this.Get('chart.shadow.offsety') < 0 ? 7 : 4),String(this.Get('chart.units.pre') + RGraph.array_sum(this.data[i]).toFixed(this.Get('chart.labels.above.decimals')) + this.Get('chart.units.post')),this.Get('chart.labels.above.angle') ? 'bottom' : null,this.Get('chart.labels.above.angle') ? (this.Get('chart.labels.above.angle') > 0 ? 'right' : 'left') : 'center',null,this.Get('chart.labels.above.angle')); |
---|
1098 | |
---|
1099 | // Turn any shadow back on |
---|
1100 | if (shadow) { |
---|
1101 | this.context.shadowColor = shadowColor; |
---|
1102 | this.context.shadowBlur = shadowBlur; |
---|
1103 | this.context.shadowOffsetX = shadowOffsetX; |
---|
1104 | this.context.shadowOffsetY = shadowOffsetY; |
---|
1105 | } |
---|
1106 | } |
---|
1107 | |
---|
1108 | |
---|
1109 | /** |
---|
1110 | * Redraw the bars if the shadow is enabled due to hem being drawn from the bottom up, and the |
---|
1111 | * shadow spilling over to higher up bars |
---|
1112 | */ |
---|
1113 | if (shadow) { |
---|
1114 | |
---|
1115 | RGraph.NoShadow(this); |
---|
1116 | |
---|
1117 | for (k=0; k<redrawCoords.length; ++k) { |
---|
1118 | this.context.strokeStyle = strokeStyle; |
---|
1119 | this.context.fillStyle = redrawCoords[k][4]; |
---|
1120 | this.context.strokeRect(redrawCoords[k][0], redrawCoords[k][1], redrawCoords[k][2], redrawCoords[k][3]); |
---|
1121 | this.context.fillRect(redrawCoords[k][0], redrawCoords[k][1], redrawCoords[k][2], redrawCoords[k][3]); |
---|
1122 | |
---|
1123 | this.context.stroke(); |
---|
1124 | this.context.fill(); |
---|
1125 | } |
---|
1126 | |
---|
1127 | // Reset the redraw coords to be empty |
---|
1128 | redrawCoords = []; |
---|
1129 | } |
---|
1130 | /** |
---|
1131 | * Grouped bar |
---|
1132 | */ |
---|
1133 | } else if (typeof(this.data[i]) == 'object' && this.Get('chart.grouping') == 'grouped') { |
---|
1134 | |
---|
1135 | var redrawCoords = []; |
---|
1136 | this.context.lineWidth = this.Get('chart.linewidth'); |
---|
1137 | |
---|
1138 | for (j=0; j<this.data[i].length; ++j) { |
---|
1139 | // Set the fill and stroke colors |
---|
1140 | this.context.strokeStyle = strokeStyle; |
---|
1141 | this.context.fillStyle = colors[j]; |
---|
1142 | |
---|
1143 | var individualBarWidth = (width - (2 * hmargin)) / this.data[i].length; |
---|
1144 | var height = (this.data[i][j] / this.max) * (RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom ); |
---|
1145 | |
---|
1146 | // If the X axis pos is in the center, we need to half the height |
---|
1147 | if (xaxispos == 'center') { |
---|
1148 | height /= 2; |
---|
1149 | } |
---|
1150 | |
---|
1151 | var startX = x + hmargin + (j * individualBarWidth); |
---|
1152 | |
---|
1153 | /** |
---|
1154 | * Determine the start positioning for the bar |
---|
1155 | */ |
---|
1156 | if (xaxispos == 'top') { |
---|
1157 | var startY = this.Get('chart.gutter.top'); |
---|
1158 | var height = Math.abs(height); |
---|
1159 | |
---|
1160 | } else if (xaxispos == 'center') { |
---|
1161 | var startY = this.gutterTop + (this.grapharea / 2) - height; |
---|
1162 | |
---|
1163 | } else { |
---|
1164 | var startY = this.canvas.height - this.gutterBottom - height; |
---|
1165 | var height = Math.abs(height); |
---|
1166 | } |
---|
1167 | |
---|
1168 | /** |
---|
1169 | * Draw MSIE shadow |
---|
1170 | */ |
---|
1171 | if (RGraph.isIE8() && shadow) { |
---|
1172 | this.DrawIEShadow([startX, startY, individualBarWidth, height]); |
---|
1173 | } |
---|
1174 | |
---|
1175 | this.context.strokeRect(startX, startY, individualBarWidth, height); |
---|
1176 | this.context.fillRect(startX, startY, individualBarWidth, height); |
---|
1177 | y += height; |
---|
1178 | |
---|
1179 | // This bit draws the text labels that appear above the bars if requested |
---|
1180 | if (this.Get('chart.labels.above')) { |
---|
1181 | |
---|
1182 | this.context.strokeStyle = 'rgba(0,0,0,0)'; |
---|
1183 | |
---|
1184 | // Turn off any shadow |
---|
1185 | if (shadow) { |
---|
1186 | RGraph.NoShadow(this); |
---|
1187 | } |
---|
1188 | |
---|
1189 | var yPos = y - 3; |
---|
1190 | |
---|
1191 | // Account for negative bars |
---|
1192 | if (this.data[i][j] < 0) { |
---|
1193 | yPos += height + 6 + (this.Get('chart.text.size') - 4); |
---|
1194 | } |
---|
1195 | |
---|
1196 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
1197 | RGraph.Text(this.context,this.Get('chart.text.font'),typeof(this.Get('chart.labels.above.size')) == 'number' ? this.Get('chart.labels.above.size') : this.Get('chart.text.size') - 3,startX + (individualBarWidth / 2),startY - 2,RGraph.number_format(this, this.data[i][j].toFixed(this.Get('chart.labels.above.decimals'))),null,this.Get('chart.labels.above.angle') ? (this.Get('chart.labels.above.angle') > 0 ? 'right' : 'left') : 'center', null, this.Get('chart.labels.above.angle')); |
---|
1198 | |
---|
1199 | // Turn any shadow back on |
---|
1200 | if (shadow) { |
---|
1201 | this.context.shadowColor = shadowColor; |
---|
1202 | this.context.shadowBlur = shadowBlur; |
---|
1203 | this.context.shadowOffsetX = shadowOffsetX; |
---|
1204 | this.context.shadowOffsetY = shadowOffsetY; |
---|
1205 | } |
---|
1206 | } |
---|
1207 | |
---|
1208 | /** |
---|
1209 | * Grouped 3D effect |
---|
1210 | */ |
---|
1211 | if (variant == '3d') { |
---|
1212 | var prevFillStyle = this.context.fillStyle; |
---|
1213 | var prevStrokeStyle = this.context.strokeStyle; |
---|
1214 | |
---|
1215 | // Draw the top side |
---|
1216 | this.context.beginPath(); |
---|
1217 | this.context.moveTo(startX, startY); |
---|
1218 | this.context.lineTo(startX + 10, startY - 5); |
---|
1219 | this.context.lineTo(startX + 10 + individualBarWidth, startY - 5); |
---|
1220 | this.context.lineTo(startX + individualBarWidth, startY); |
---|
1221 | this.context.closePath(); |
---|
1222 | |
---|
1223 | this.context.fill(); |
---|
1224 | this.context.stroke(); |
---|
1225 | |
---|
1226 | // Draw the side section |
---|
1227 | this.context.beginPath(); |
---|
1228 | this.context.moveTo(startX + individualBarWidth, startY); |
---|
1229 | this.context.lineTo(startX + individualBarWidth + 10, startY - 5); |
---|
1230 | this.context.lineTo(startX + individualBarWidth + 10, startY - 5 + height); |
---|
1231 | this.context.lineTo(startX + individualBarWidth , startY + height); |
---|
1232 | this.context.closePath(); |
---|
1233 | |
---|
1234 | this.context.fill(); |
---|
1235 | this.context.stroke(); |
---|
1236 | |
---|
1237 | |
---|
1238 | // Draw the darker top side |
---|
1239 | this.context.fillStyle = 'rgba(255,255,255,0.3)'; |
---|
1240 | this.context.beginPath(); |
---|
1241 | this.context.moveTo(startX, startY); |
---|
1242 | this.context.lineTo(startX + 10, startY - 5); |
---|
1243 | this.context.lineTo(startX + 10 + individualBarWidth, startY - 5); |
---|
1244 | this.context.lineTo(startX + individualBarWidth, startY); |
---|
1245 | this.context.closePath(); |
---|
1246 | |
---|
1247 | this.context.fill(); |
---|
1248 | this.context.stroke(); |
---|
1249 | |
---|
1250 | // Draw the darker side section |
---|
1251 | this.context.fillStyle = 'rgba(0,0,0,0.4)'; |
---|
1252 | this.context.beginPath(); |
---|
1253 | this.context.moveTo(startX + individualBarWidth, startY); |
---|
1254 | this.context.lineTo(startX + individualBarWidth + 10, startY - 5); |
---|
1255 | this.context.lineTo(startX + individualBarWidth + 10, startY - 5 + height); |
---|
1256 | this.context.lineTo(startX + individualBarWidth , startY + height); |
---|
1257 | this.context.closePath(); |
---|
1258 | |
---|
1259 | this.context.fill(); |
---|
1260 | this.context.stroke(); |
---|
1261 | |
---|
1262 | this.context.strokeStyle = prevStrokeStyle; |
---|
1263 | this.context.fillStyle = prevFillStyle; |
---|
1264 | } |
---|
1265 | |
---|
1266 | this.coords.push([startX, startY, individualBarWidth, height]); |
---|
1267 | |
---|
1268 | // Facilitate shadows going to the left |
---|
1269 | if (this.Get('chart.shadow')) { |
---|
1270 | redrawCoords.push([startX, startY, individualBarWidth, height]); |
---|
1271 | } |
---|
1272 | } |
---|
1273 | |
---|
1274 | /** |
---|
1275 | * Redraw the bar if shadows are going to the left |
---|
1276 | */ |
---|
1277 | if (redrawCoords.length) { |
---|
1278 | |
---|
1279 | RGraph.NoShadow(this); |
---|
1280 | |
---|
1281 | this.context.lineWidth = this.Get('chart.linewidth'); |
---|
1282 | |
---|
1283 | this.context.beginPath(); |
---|
1284 | for (var j=0; j<redrawCoords.length; ++j) { |
---|
1285 | |
---|
1286 | this.context.fillStyle = this.Get('chart.colors')[j]; |
---|
1287 | this.context.strokeStyle = this.Get('chart.strokecolor'); |
---|
1288 | |
---|
1289 | this.context.fillRect(redrawCoords[j][0], redrawCoords[j][1], redrawCoords[j][2], redrawCoords[j][3]); |
---|
1290 | this.context.strokeRect(redrawCoords[j][0], redrawCoords[j][1], redrawCoords[j][2], redrawCoords[j][3]); |
---|
1291 | } |
---|
1292 | this.context.fill(); |
---|
1293 | this.context.stroke(); |
---|
1294 | |
---|
1295 | redrawCoords = []; |
---|
1296 | } |
---|
1297 | } |
---|
1298 | |
---|
1299 | this.context.closePath(); |
---|
1300 | } |
---|
1301 | |
---|
1302 | /** |
---|
1303 | * Turn off any shadow |
---|
1304 | */ |
---|
1305 | RGraph.NoShadow(this); |
---|
1306 | |
---|
1307 | |
---|
1308 | /** |
---|
1309 | * Install the onclick event handler |
---|
1310 | */ |
---|
1311 | if (this.Get('chart.tooltips')) { |
---|
1312 | |
---|
1313 | // Need to register this object for redrawing |
---|
1314 | RGraph.Register(this); |
---|
1315 | |
---|
1316 | /** |
---|
1317 | * Install the window onclick handler |
---|
1318 | */ |
---|
1319 | var window_onclick_func = function (){RGraph.Redraw();}; |
---|
1320 | window.addEventListener('click', window_onclick_func, false); |
---|
1321 | RGraph.AddEventListener('window_' + this.id, 'click', window_onclick_func); |
---|
1322 | |
---|
1323 | |
---|
1324 | |
---|
1325 | /** |
---|
1326 | * If the cursor is over a hotspot, change the cursor to a hand. Bar chart tooltips can now |
---|
1327 | * be based around the onmousemove event |
---|
1328 | */ |
---|
1329 | canvas_onmousemove = function (e) |
---|
1330 | { |
---|
1331 | e = RGraph.FixEventObject(e); |
---|
1332 | |
---|
1333 | var canvas = document.getElementById(e.target.id); |
---|
1334 | var obj = canvas.__object__; |
---|
1335 | var barCoords = obj.getBar(e); |
---|
1336 | |
---|
1337 | /** |
---|
1338 | * If there are bar coords AND the bar has height |
---|
1339 | */ |
---|
1340 | |
---|
1341 | if (barCoords && barCoords[4] > 0) { |
---|
1342 | |
---|
1343 | /** |
---|
1344 | * Get the tooltip text |
---|
1345 | */ |
---|
1346 | if (typeof(obj.Get('chart.tooltips')) == 'function') { |
---|
1347 | var text = String(obj.Get('chart.tooltips')(barCoords[5])); |
---|
1348 | |
---|
1349 | } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'function') { |
---|
1350 | var text = String(obj.Get('chart.tooltips')[barCoords[5]](barCoords[5])); |
---|
1351 | |
---|
1352 | } else if (typeof(obj.Get('chart.tooltips')) == 'object' && (typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'string' || typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'number')) { |
---|
1353 | var text = String(obj.Get('chart.tooltips')[barCoords[5]]); |
---|
1354 | |
---|
1355 | } else { |
---|
1356 | var text = null; |
---|
1357 | } |
---|
1358 | |
---|
1359 | if (text) { |
---|
1360 | canvas.style.cursor = 'pointer'; |
---|
1361 | } else { |
---|
1362 | canvas.style.cursor = 'default'; |
---|
1363 | } |
---|
1364 | |
---|
1365 | /** |
---|
1366 | * Hide the currently displayed tooltip if the index is the same |
---|
1367 | */ |
---|
1368 | if ( RGraph.Registry.Get('chart.tooltip') |
---|
1369 | && RGraph.Registry.Get('chart.tooltip').__canvas__.id != obj.id |
---|
1370 | && obj.Get('chart.tooltips.event') == 'onmousemove') { |
---|
1371 | |
---|
1372 | RGraph.Redraw(); |
---|
1373 | RGraph.HideTooltip(); |
---|
1374 | } |
---|
1375 | |
---|
1376 | /** |
---|
1377 | * This facilitates the tooltips using the onmousemove event |
---|
1378 | */ |
---|
1379 | |
---|
1380 | if ( obj.Get('chart.tooltips.event') == 'onmousemove' |
---|
1381 | && ( |
---|
1382 | (RGraph.Registry.Get('chart.tooltip') && RGraph.Registry.Get('chart.tooltip').__index__ != barCoords[5]) |
---|
1383 | || !RGraph.Registry.Get('chart.tooltip') |
---|
1384 | ) |
---|
1385 | && text) { |
---|
1386 | /** |
---|
1387 | * Show a tooltip if it's defined |
---|
1388 | */ |
---|
1389 | RGraph.Redraw(obj); |
---|
1390 | |
---|
1391 | if (obj.Get('chart.tooltips.highlight')) { |
---|
1392 | obj.context.beginPath(); |
---|
1393 | obj.context.strokeStyle = obj.Get('chart.highlight.stroke'); |
---|
1394 | obj.context.fillStyle = obj.Get('chart.highlight.fill'); |
---|
1395 | obj.context.strokeRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); |
---|
1396 | obj.context.fillRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); |
---|
1397 | |
---|
1398 | obj.context.stroke(); |
---|
1399 | obj.context.fill(); |
---|
1400 | } |
---|
1401 | |
---|
1402 | RGraph.Tooltip(canvas, text, e.pageX, e.pageY, barCoords[5]); |
---|
1403 | } |
---|
1404 | } else { |
---|
1405 | canvas.style.cursor = 'default'; |
---|
1406 | } |
---|
1407 | } |
---|
1408 | RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove); |
---|
1409 | this.canvas.addEventListener('mousemove', canvas_onmousemove, false); |
---|
1410 | |
---|
1411 | |
---|
1412 | /** |
---|
1413 | * Install the onclick event handler for the tooltips |
---|
1414 | */ |
---|
1415 | if (this.Get('chart.tooltips.event') == 'onclick') { |
---|
1416 | |
---|
1417 | canvas_onclick = function (e) |
---|
1418 | { |
---|
1419 | var e = RGraph.FixEventObject(e); |
---|
1420 | |
---|
1421 | // If the button pressed isn't the left, we're not interested |
---|
1422 | if (e.button != 0) return; |
---|
1423 | |
---|
1424 | e = RGraph.FixEventObject(e); |
---|
1425 | |
---|
1426 | var canvas = document.getElementById(this.id); |
---|
1427 | var obj = canvas.__object__; |
---|
1428 | var barCoords = obj.getBar(e); |
---|
1429 | |
---|
1430 | /** |
---|
1431 | * Redraw the graph first, in effect resetting the graph to as it was when it was first drawn |
---|
1432 | * This "deselects" any already selected bar |
---|
1433 | */ |
---|
1434 | RGraph.Redraw(); |
---|
1435 | |
---|
1436 | /** |
---|
1437 | * Loop through the bars determining if the mouse is over a bar |
---|
1438 | */ |
---|
1439 | if (barCoords) { |
---|
1440 | |
---|
1441 | /** |
---|
1442 | * Get the tooltip text |
---|
1443 | */ |
---|
1444 | if (typeof(obj.Get('chart.tooltips')) == 'function') { |
---|
1445 | var text = String(obj.Get('chart.tooltips')(barCoords[5])); |
---|
1446 | |
---|
1447 | } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[barCoords[5]]) == 'function') { |
---|
1448 | var text = String(obj.Get('chart.tooltips')[barCoords[5]](barCoords[5])); |
---|
1449 | |
---|
1450 | } else if (typeof(obj.Get('chart.tooltips')) == 'object') { |
---|
1451 | var text = String(obj.Get('chart.tooltips')[barCoords[5]]); |
---|
1452 | |
---|
1453 | } else { |
---|
1454 | var text = null; |
---|
1455 | } |
---|
1456 | |
---|
1457 | /** |
---|
1458 | * Show a tooltip if it's defined |
---|
1459 | */ |
---|
1460 | if (text && text != 'undefined') { |
---|
1461 | |
---|
1462 | if (obj.Get('chart.tooltips.highlight')) { |
---|
1463 | // [TODO] Allow customisation of the highlight colors |
---|
1464 | obj.context.beginPath(); |
---|
1465 | obj.context.strokeStyle = obj.Get('chart.highlight.stroke'); |
---|
1466 | obj.context.fillStyle = obj.Get('chart.highlight.fill'); |
---|
1467 | obj.context.strokeRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); |
---|
1468 | obj.context.fillRect(barCoords[1], barCoords[2], barCoords[3], barCoords[4]); |
---|
1469 | |
---|
1470 | obj.context.stroke(); |
---|
1471 | obj.context.fill(); |
---|
1472 | } |
---|
1473 | |
---|
1474 | RGraph.Tooltip(canvas, text, e.pageX, e.pageY, barCoords[5]); |
---|
1475 | } |
---|
1476 | } |
---|
1477 | |
---|
1478 | /** |
---|
1479 | * Stop the event bubbling |
---|
1480 | */ |
---|
1481 | e.stopPropagation(); |
---|
1482 | } |
---|
1483 | RGraph.AddEventListener(this.id, 'click', canvas_onclick); |
---|
1484 | this.canvas.addEventListener('click', canvas_onclick, false); |
---|
1485 | } |
---|
1486 | |
---|
1487 | |
---|
1488 | // This resets the bar graph |
---|
1489 | // 8th August 2010 : Is this redundant |
---|
1490 | //if (typeof(obj) != 'undefined' && obj == RGraph.Registry.Get('chart.tooltip')) { |
---|
1491 | // obj.style.display = 'none'; |
---|
1492 | // RGraph.Registry.Set('chart.tooltip', null) |
---|
1493 | //} |
---|
1494 | } |
---|
1495 | } |
---|
1496 | |
---|
1497 | /** |
---|
1498 | * Draws the labels for the graph |
---|
1499 | */ |
---|
1500 | RGraph.Bar.prototype.DrawLabels = function () |
---|
1501 | { |
---|
1502 | var context = this.context; |
---|
1503 | var text_angle = this.Get('chart.text.angle'); |
---|
1504 | var text_size = this.Get('chart.text.size'); |
---|
1505 | var labels = this.Get('chart.labels'); |
---|
1506 | |
---|
1507 | |
---|
1508 | // Draw the Y axis labels: |
---|
1509 | if (this.Get('chart.ylabels')) { |
---|
1510 | this.Drawlabels_top(); |
---|
1511 | this.Drawlabels_center(); |
---|
1512 | this.Drawlabels_bottom(); |
---|
1513 | } |
---|
1514 | |
---|
1515 | /** |
---|
1516 | * The X axis labels |
---|
1517 | */ |
---|
1518 | if (typeof(labels) == 'object' && labels) { |
---|
1519 | |
---|
1520 | var yOffset = 13 + Number(this.Get('chart.xlabels.offset')); |
---|
1521 | |
---|
1522 | /** |
---|
1523 | * Text angle |
---|
1524 | */ |
---|
1525 | var angle = 0; |
---|
1526 | var halign = 'center'; |
---|
1527 | |
---|
1528 | if (text_angle > 0) { |
---|
1529 | angle = -1 * text_angle; |
---|
1530 | halign = 'right'; |
---|
1531 | yOffset -= 5; |
---|
1532 | |
---|
1533 | if (this.Get('chart.xaxispos') == 'top') { |
---|
1534 | halign = 'left'; |
---|
1535 | yOffset += 5; |
---|
1536 | } |
---|
1537 | } |
---|
1538 | |
---|
1539 | // Draw the X axis labels |
---|
1540 | context.fillStyle = this.Get('chart.text.color'); |
---|
1541 | |
---|
1542 | // How wide is each bar |
---|
1543 | var barWidth = (RGraph.GetWidth(this) - this.gutterRight - this.gutterLeft) / labels.length; |
---|
1544 | |
---|
1545 | // Reset the xTickGap |
---|
1546 | xTickGap = (RGraph.GetWidth(this) - this.gutterRight - this.gutterLeft) / labels.length |
---|
1547 | |
---|
1548 | // Draw the X tickmarks |
---|
1549 | var i=0; |
---|
1550 | var font = this.Get('chart.text.font'); |
---|
1551 | |
---|
1552 | for (x=this.gutterLeft + (xTickGap / 2); x<=RGraph.GetWidth(this) - this.gutterRight; x+=xTickGap) { |
---|
1553 | RGraph.Text(context, font, |
---|
1554 | text_size, |
---|
1555 | x + (this.Get('chart.text.angle') == 90 ? 0 : 0), |
---|
1556 | this.Get('chart.xaxispos') == 'top' ? this.gutterTop - yOffset + text_size - 1: (RGraph.GetHeight(this) - this.gutterBottom) + yOffset, |
---|
1557 | String(labels[i++]), |
---|
1558 | (this.Get('chart.text.angle') == 90 ? 'center' : null), |
---|
1559 | halign, |
---|
1560 | null, |
---|
1561 | angle); |
---|
1562 | } |
---|
1563 | } |
---|
1564 | } |
---|
1565 | |
---|
1566 | /** |
---|
1567 | * Draws the X axis at the top |
---|
1568 | */ |
---|
1569 | RGraph.Bar.prototype.Drawlabels_top = function () |
---|
1570 | { |
---|
1571 | this.context.beginPath(); |
---|
1572 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
1573 | this.context.strokeStyle = 'black'; |
---|
1574 | |
---|
1575 | if (this.Get('chart.xaxispos') == 'top') { |
---|
1576 | |
---|
1577 | var context = this.context; |
---|
1578 | var interval = (this.grapharea * (1/5) ); |
---|
1579 | var text_size = this.Get('chart.text.size'); |
---|
1580 | var units_pre = this.Get('chart.units.pre'); |
---|
1581 | var units_post = this.Get('chart.units.post'); |
---|
1582 | var align = this.Get('chart.yaxispos') == 'left' ? 'right' : 'left'; |
---|
1583 | var font = this.Get('chart.text.font'); |
---|
1584 | var numYLabels = this.Get('chart.ylabels.count'); |
---|
1585 | |
---|
1586 | if (this.Get('chart.ylabels.inside') == true) { |
---|
1587 | var xpos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft + 5 : RGraph.GetWidth(this) - this.gutterRight - 5; |
---|
1588 | var align = this.Get('chart.yaxispos') == 'left' ? 'left' : 'right'; |
---|
1589 | var boxed = true; |
---|
1590 | } else { |
---|
1591 | var xpos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft - 5 : this.canvas.width - this.gutterRight + 5; |
---|
1592 | var boxed = false; |
---|
1593 | } |
---|
1594 | |
---|
1595 | /** |
---|
1596 | * Draw specific Y labels here so that the local variables can be reused |
---|
1597 | */ |
---|
1598 | if (typeof(this.Get('chart.ylabels.specific')) == 'object' && this.Get('chart.ylabels.specific')) { |
---|
1599 | |
---|
1600 | var labels = RGraph.array_reverse(this.Get('chart.ylabels.specific')); |
---|
1601 | var grapharea = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
1602 | |
---|
1603 | for (var i=0; i<labels.length; ++i) { |
---|
1604 | |
---|
1605 | var y = this.gutterTop + (grapharea * (i / labels.length)) + (grapharea / labels.length); |
---|
1606 | |
---|
1607 | RGraph.Text(context, font, text_size, xpos, y, labels[i], 'center', align, boxed); |
---|
1608 | } |
---|
1609 | |
---|
1610 | return; |
---|
1611 | } |
---|
1612 | |
---|
1613 | // 1(ish) label |
---|
1614 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1615 | RGraph.Text(context, font, text_size, xpos, this.gutterTop + this.halfTextHeight + interval, '-' + RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, boxed); |
---|
1616 | |
---|
1617 | // 5 labels |
---|
1618 | if (numYLabels == 5) { |
---|
1619 | RGraph.Text(context, font, text_size, xpos, (1*interval) + this.gutterTop + this.halfTextHeight + interval, '-' + RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, boxed); |
---|
1620 | RGraph.Text(context, font, text_size, xpos, (3*interval) + this.gutterTop + this.halfTextHeight + interval, '-' + RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, boxed); |
---|
1621 | } |
---|
1622 | |
---|
1623 | // 3 labels |
---|
1624 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1625 | RGraph.Text(context, font, text_size, xpos, (2*interval) + this.gutterTop + this.halfTextHeight + interval, '-' + RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, boxed); |
---|
1626 | RGraph.Text(context, font, text_size, xpos, (4*interval) + this.gutterTop + this.halfTextHeight + interval, '-' + RGraph.number_format(this, this.scale[4], units_pre, units_post), null, align, boxed); |
---|
1627 | } |
---|
1628 | } |
---|
1629 | |
---|
1630 | // 10 Y labels |
---|
1631 | if (numYLabels == 10) { |
---|
1632 | |
---|
1633 | interval = (this.grapharea / numYLabels ); |
---|
1634 | |
---|
1635 | for (var i=10; i>0; --i) { |
---|
1636 | RGraph.Text(context, font, text_size, xpos,this.gutterTop + ((this.grapharea / numYLabels) * i),'-' + RGraph.number_format(this,((this.scale[4] / numYLabels) * i).toFixed((this.Get('chart.scale.decimals'))), units_pre, units_post), 'center', align, boxed); |
---|
1637 | } |
---|
1638 | } |
---|
1639 | } |
---|
1640 | |
---|
1641 | this.context.fill(); |
---|
1642 | this.context.stroke(); |
---|
1643 | } |
---|
1644 | |
---|
1645 | /** |
---|
1646 | * Draws the X axis in the middle |
---|
1647 | */ |
---|
1648 | RGraph.Bar.prototype.Drawlabels_center = function () |
---|
1649 | { |
---|
1650 | var font = this.Get('chart.text.font'); |
---|
1651 | var numYLabels = this.Get('chart.ylabels.count'); |
---|
1652 | |
---|
1653 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
1654 | |
---|
1655 | if (this.Get('chart.xaxispos') == 'center') { |
---|
1656 | |
---|
1657 | /** |
---|
1658 | * Draw the top labels |
---|
1659 | */ |
---|
1660 | var interval = (this.grapharea * (1/10) ); |
---|
1661 | var text_size = this.Get('chart.text.size'); |
---|
1662 | var units_pre = this.Get('chart.units.pre'); |
---|
1663 | var units_post = this.Get('chart.units.post'); |
---|
1664 | var context = this.context; |
---|
1665 | var align = ''; |
---|
1666 | var xpos = 0; |
---|
1667 | var boxed = false; |
---|
1668 | |
---|
1669 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
1670 | this.context.strokeStyle = 'black'; |
---|
1671 | |
---|
1672 | if (this.Get('chart.ylabels.inside') == true) { |
---|
1673 | var xpos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft + 5 : RGraph.GetWidth(this) - this.gutterRight - 5; |
---|
1674 | var align = this.Get('chart.yaxispos') == 'left' ? 'left' : 'right'; |
---|
1675 | var boxed = true; |
---|
1676 | } else { |
---|
1677 | var xpos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft - 5 : RGraph.GetWidth(this) - this.gutterRight + 5; |
---|
1678 | var align = this.Get('chart.yaxispos') == 'left' ? 'right' : 'left'; |
---|
1679 | var boxed = false; |
---|
1680 | } |
---|
1681 | |
---|
1682 | |
---|
1683 | |
---|
1684 | |
---|
1685 | |
---|
1686 | |
---|
1687 | |
---|
1688 | |
---|
1689 | |
---|
1690 | |
---|
1691 | |
---|
1692 | |
---|
1693 | /** |
---|
1694 | * Draw specific Y labels here so that the local variables can be reused |
---|
1695 | */ |
---|
1696 | if (typeof(this.Get('chart.ylabels.specific')) == 'object' && this.Get('chart.ylabels.specific')) { |
---|
1697 | |
---|
1698 | var labels = this.Get('chart.ylabels.specific'); |
---|
1699 | var grapharea = this.canvas.height - this.gutterTop - this.gutterBottom; |
---|
1700 | |
---|
1701 | // Draw the top halves labels |
---|
1702 | for (var i=0; i<labels.length; ++i) { |
---|
1703 | |
---|
1704 | var y = this.gutterTop + ((grapharea / 2) / labels.length) * i; |
---|
1705 | |
---|
1706 | RGraph.Text(context, font, text_size, xpos, y, String(labels[i]), 'center', align, boxed); |
---|
1707 | } |
---|
1708 | |
---|
1709 | // Draw the bottom halves labels |
---|
1710 | for (var i=labels.length-1; i>=0; --i) { |
---|
1711 | var y = this.gutterTop + (grapharea * ( (i+1) / (labels.length * 2) )) + (grapharea / 2); |
---|
1712 | |
---|
1713 | RGraph.Text(context, font, text_size, xpos, y, labels[labels.length - i - 1], 'center', align, boxed); |
---|
1714 | } |
---|
1715 | |
---|
1716 | return; |
---|
1717 | } |
---|
1718 | |
---|
1719 | |
---|
1720 | |
---|
1721 | |
---|
1722 | |
---|
1723 | |
---|
1724 | |
---|
1725 | |
---|
1726 | |
---|
1727 | |
---|
1728 | |
---|
1729 | |
---|
1730 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1731 | RGraph.Text(context, font, text_size, xpos, this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[4], units_pre, units_post), null, align, boxed); |
---|
1732 | |
---|
1733 | if (numYLabels == 5) { |
---|
1734 | RGraph.Text(context, font, text_size, xpos, (1*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, boxed); |
---|
1735 | RGraph.Text(context, font, text_size, xpos, (3*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, boxed); |
---|
1736 | } |
---|
1737 | |
---|
1738 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1739 | RGraph.Text(context, font, text_size, xpos, (4*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, boxed); |
---|
1740 | RGraph.Text(context, font, text_size, xpos, (2*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, boxed); |
---|
1741 | } |
---|
1742 | } else if (numYLabels == 10) { |
---|
1743 | // 10Y labels |
---|
1744 | interval = (this.grapharea / numYLabels) / 2; |
---|
1745 | |
---|
1746 | for (var i=0; i<numYLabels; ++i) { |
---|
1747 | RGraph.Text(context, font, text_size, xpos,this.gutterTop + ((this.grapharea / (numYLabels * 2)) * i),RGraph.number_format(this, ((this.scale[4] / numYLabels) * (numYLabels - i)).toFixed((this.Get('chart.scale.decimals'))), units_pre, units_post), 'center', align, boxed); |
---|
1748 | } |
---|
1749 | } |
---|
1750 | /////////////////////////////////////////////////////////////////////////////////// |
---|
1751 | |
---|
1752 | /** |
---|
1753 | * Draw the bottom (X axis) labels |
---|
1754 | */ |
---|
1755 | var interval = (this.grapharea) / 10; |
---|
1756 | |
---|
1757 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1758 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1759 | RGraph.Text(context, font, text_size, xpos, (this.grapharea + this.gutterTop + this.halfTextHeight) - (4 * interval), '-' + RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, boxed); |
---|
1760 | RGraph.Text(context, font, text_size, xpos, (this.grapharea + this.gutterTop + this.halfTextHeight) - (2 * interval), '-' + RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, boxed); |
---|
1761 | } |
---|
1762 | |
---|
1763 | if (numYLabels == 5) { |
---|
1764 | RGraph.Text(context, font, text_size, xpos, (this.grapharea + this.gutterTop + this.halfTextHeight) - (3 * interval), '-' + RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, boxed); |
---|
1765 | RGraph.Text(context, font, text_size, xpos, (this.grapharea + this.gutterTop + this.halfTextHeight) - interval, '-' + RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, boxed); |
---|
1766 | } |
---|
1767 | |
---|
1768 | RGraph.Text(context, font, text_size, xpos, this.grapharea + this.gutterTop + this.halfTextHeight, '-' + RGraph.number_format(this, this.scale[4], units_pre, units_post), null, align, boxed); |
---|
1769 | |
---|
1770 | } else if (numYLabels == 10) { |
---|
1771 | |
---|
1772 | // Arbitrary number of Y labels |
---|
1773 | interval = (this.grapharea / numYLabels) / 2; |
---|
1774 | |
---|
1775 | for (var i=0; i<numYLabels; ++i) { |
---|
1776 | RGraph.Text(context, font, text_size, xpos,this.gutterTop + (this.grapharea / 2) + ((this.grapharea / (numYLabels * 2)) * i) + (this.grapharea / (numYLabels * 2)),RGraph.number_format(this, ((this.scale[4] / numYLabels) * (i+1)).toFixed((this.Get('chart.scale.decimals'))), '-' + units_pre, units_post),'center', align, boxed); |
---|
1777 | } |
---|
1778 | } |
---|
1779 | |
---|
1780 | |
---|
1781 | |
---|
1782 | } |
---|
1783 | } |
---|
1784 | |
---|
1785 | /** |
---|
1786 | * Draws the X axdis at the bottom (the default) |
---|
1787 | */ |
---|
1788 | RGraph.Bar.prototype.Drawlabels_bottom = function () |
---|
1789 | { |
---|
1790 | this.context.beginPath(); |
---|
1791 | this.context.fillStyle = this.Get('chart.text.color'); |
---|
1792 | this.context.strokeStyle = 'black'; |
---|
1793 | |
---|
1794 | if (this.Get('chart.xaxispos') != 'center' && this.Get('chart.xaxispos') != 'top') { |
---|
1795 | |
---|
1796 | var interval = (this.grapharea * (1/5) ); |
---|
1797 | var text_size = this.Get('chart.text.size'); |
---|
1798 | var units_pre = this.Get('chart.units.pre'); |
---|
1799 | var units_post = this.Get('chart.units.post'); |
---|
1800 | var context = this.context; |
---|
1801 | var align = this.Get('chart.yaxispos') == 'left' ? 'right' : 'left'; |
---|
1802 | var font = this.Get('chart.text.font'); |
---|
1803 | var numYLabels = this.Get('chart.ylabels.count'); |
---|
1804 | |
---|
1805 | if (this.Get('chart.ylabels.inside') == true) { |
---|
1806 | var xpos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft + 5 : RGraph.GetWidth(this) - this.gutterRight - 5; |
---|
1807 | var align = this.Get('chart.yaxispos') == 'left' ? 'left' : 'right'; |
---|
1808 | var boxed = true; |
---|
1809 | } else { |
---|
1810 | var xpos = this.Get('chart.yaxispos') == 'left' ? this.gutterLeft - 5 : RGraph.GetWidth(this) - this.gutterRight + 5; |
---|
1811 | var boxed = false; |
---|
1812 | } |
---|
1813 | |
---|
1814 | /** |
---|
1815 | * Draw specific Y labels here so that the local variables can be reused |
---|
1816 | */ |
---|
1817 | if (this.Get('chart.ylabels.specific') && typeof(this.Get('chart.ylabels.specific')) == 'object') { |
---|
1818 | |
---|
1819 | var labels = this.Get('chart.ylabels.specific'); |
---|
1820 | var grapharea = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; |
---|
1821 | |
---|
1822 | for (var i=0; i<labels.length; ++i) { |
---|
1823 | var y = this.gutterTop + (grapharea * (i / labels.length)); |
---|
1824 | |
---|
1825 | RGraph.Text(context, font, text_size, xpos, y, labels[i], 'center', align, boxed); |
---|
1826 | } |
---|
1827 | |
---|
1828 | return; |
---|
1829 | } |
---|
1830 | |
---|
1831 | // 1 label |
---|
1832 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1833 | RGraph.Text(context, font, text_size, xpos, this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[4], units_pre, units_post), null, align, boxed); |
---|
1834 | |
---|
1835 | // 5 labels |
---|
1836 | if (numYLabels == 5) { |
---|
1837 | RGraph.Text(context, font, text_size, xpos, (1*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[3], units_pre, units_post), null, align, boxed); |
---|
1838 | RGraph.Text(context, font, text_size, xpos, (3*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[1], units_pre, units_post), null, align, boxed); |
---|
1839 | } |
---|
1840 | |
---|
1841 | // 3 labels |
---|
1842 | if (numYLabels == 3 || numYLabels == 5) { |
---|
1843 | RGraph.Text(context, font, text_size, xpos, (2*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[2], units_pre, units_post), null, align, boxed); |
---|
1844 | RGraph.Text(context, font, text_size, xpos, (4*interval) + this.gutterTop + this.halfTextHeight, RGraph.number_format(this, this.scale[0], units_pre, units_post), null, align, boxed); |
---|
1845 | } |
---|
1846 | } |
---|
1847 | |
---|
1848 | // 10 Y labels |
---|
1849 | if (numYLabels == 10) { |
---|
1850 | |
---|
1851 | interval = (this.grapharea / numYLabels ); |
---|
1852 | |
---|
1853 | for (var i=0; i<numYLabels; ++i) { |
---|
1854 | RGraph.Text(context, font, text_size, xpos, this.gutterTop + ((this.grapharea / numYLabels) * i), RGraph.number_format(this,((this.scale[4] / numYLabels) * (numYLabels - i)).toFixed((this.Get('chart.scale.decimals'))), units_pre, units_post), 'center', align, boxed); |
---|
1855 | } |
---|
1856 | } |
---|
1857 | } |
---|
1858 | |
---|
1859 | this.context.fill(); |
---|
1860 | this.context.stroke(); |
---|
1861 | } |
---|
1862 | |
---|
1863 | |
---|
1864 | /** |
---|
1865 | * This function is used by MSIE only to manually draw the shadow |
---|
1866 | * |
---|
1867 | * @param array coords The coords for the bar |
---|
1868 | */ |
---|
1869 | RGraph.Bar.prototype.DrawIEShadow = function (coords) |
---|
1870 | { |
---|
1871 | var prevFillStyle = this.context.fillStyle; |
---|
1872 | var offsetx = this.Get('chart.shadow.offsetx'); |
---|
1873 | var offsety = this.Get('chart.shadow.offsety'); |
---|
1874 | |
---|
1875 | this.context.lineWidth = this.Get('chart.linewidth'); |
---|
1876 | this.context.fillStyle = this.Get('chart.shadow.color'); |
---|
1877 | this.context.beginPath(); |
---|
1878 | |
---|
1879 | // Draw shadow here |
---|
1880 | this.context.fillRect(coords[0] + offsetx, coords[1] + offsety, coords[2], coords[3]); |
---|
1881 | |
---|
1882 | this.context.fill(); |
---|
1883 | |
---|
1884 | // Change the fillstyle back to what it was |
---|
1885 | this.context.fillStyle = prevFillStyle; |
---|
1886 | } |
---|
1887 | |
---|
1888 | |
---|
1889 | /** |
---|
1890 | * Not used by the class during creating the graph, but is used by event handlers |
---|
1891 | * to get the coordinates (if any) of the selected bar |
---|
1892 | */ |
---|
1893 | RGraph.Bar.prototype.getBar = function (e) |
---|
1894 | { |
---|
1895 | var canvas = e.target; |
---|
1896 | var obj = e.target.__object__; |
---|
1897 | var mouseCoords = RGraph.getMouseXY(e); |
---|
1898 | |
---|
1899 | /** |
---|
1900 | * Loop through the bars determining if the mouse is over a bar |
---|
1901 | */ |
---|
1902 | for (var i=0; i<obj.coords.length; i++) { |
---|
1903 | |
---|
1904 | var mouseX = mouseCoords[0]; |
---|
1905 | var mouseY = mouseCoords[1]; |
---|
1906 | |
---|
1907 | var left = obj.coords[i][0]; |
---|
1908 | var top = obj.coords[i][1]; |
---|
1909 | var width = obj.coords[i][2]; |
---|
1910 | var height = obj.coords[i][3]; |
---|
1911 | |
---|
1912 | if ( mouseX >= left |
---|
1913 | && mouseX <= left + width |
---|
1914 | && mouseY >= top |
---|
1915 | && mouseY <= top + height) { |
---|
1916 | |
---|
1917 | return [obj, left, top, width, height, i]; |
---|
1918 | } |
---|
1919 | } |
---|
1920 | |
---|
1921 | return null; |
---|
1922 | } |
---|