@kevinburke/flot 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +1814 -0
  2. package/LICENSE.txt +22 -0
  3. package/README.md +119 -0
  4. package/dist/flot.js +9830 -0
  5. package/dist/flot.min.js +2 -0
  6. package/dist/flot.min.js.map +1 -0
  7. package/dist/flot.mjs +9805 -0
  8. package/dist/jquery.flot.js +9869 -0
  9. package/dist/jquery.flot.min.js +2 -0
  10. package/dist/jquery.flot.min.js.map +1 -0
  11. package/dist/plugins/jquery.flot.crosshair.js +207 -0
  12. package/dist/plugins/jquery.flot.crosshair.min.js +2 -0
  13. package/dist/plugins/jquery.flot.crosshair.min.js.map +1 -0
  14. package/dist/plugins/jquery.flot.image.js +261 -0
  15. package/dist/plugins/jquery.flot.image.min.js +2 -0
  16. package/dist/plugins/jquery.flot.image.min.js.map +1 -0
  17. package/dist/plugins/jquery.flot.pie.js +815 -0
  18. package/dist/plugins/jquery.flot.pie.min.js +2 -0
  19. package/dist/plugins/jquery.flot.pie.min.js.map +1 -0
  20. package/dist/plugins/jquery.flot.resize.js +62 -0
  21. package/dist/plugins/jquery.flot.resize.min.js +2 -0
  22. package/dist/plugins/jquery.flot.resize.min.js.map +1 -0
  23. package/dist/plugins/jquery.flot.threshold.js +148 -0
  24. package/dist/plugins/jquery.flot.threshold.min.js +2 -0
  25. package/dist/plugins/jquery.flot.threshold.min.js.map +1 -0
  26. package/docs/API.md +1767 -0
  27. package/docs/PLUGINS.md +143 -0
  28. package/docs/absRelTime.md +42 -0
  29. package/docs/browser.md +24 -0
  30. package/docs/canvaswrapper.md +116 -0
  31. package/docs/composeImages.md +32 -0
  32. package/docs/drawSeries.md +35 -0
  33. package/docs/hover.md +21 -0
  34. package/docs/interactions.md +57 -0
  35. package/docs/logaxis.md +27 -0
  36. package/docs/navigate.md +110 -0
  37. package/package.json +53 -0
  38. package/source/helpers.js +168 -0
  39. package/source/index.js +70 -0
  40. package/source/jquery-adapter.js +83 -0
  41. package/source/jquery.canvaswrapper.js +546 -0
  42. package/source/jquery.colorhelpers.js +198 -0
  43. package/source/jquery.flot.axislabels.js +214 -0
  44. package/source/jquery.flot.browser.js +53 -0
  45. package/source/jquery.flot.categories.js +202 -0
  46. package/source/jquery.flot.composeImages.js +327 -0
  47. package/source/jquery.flot.crosshair.js +203 -0
  48. package/source/jquery.flot.drawSeries.js +699 -0
  49. package/source/jquery.flot.errorbars.js +375 -0
  50. package/source/jquery.flot.fillbetween.js +254 -0
  51. package/source/jquery.flot.flatdata.js +47 -0
  52. package/source/jquery.flot.hover.js +354 -0
  53. package/source/jquery.flot.image.js +252 -0
  54. package/source/jquery.flot.js +2814 -0
  55. package/source/jquery.flot.legend.js +444 -0
  56. package/source/jquery.flot.logaxis.js +299 -0
  57. package/source/jquery.flot.navigate.js +842 -0
  58. package/source/jquery.flot.pie.js +811 -0
  59. package/source/jquery.flot.resize.js +57 -0
  60. package/source/jquery.flot.saturated.js +40 -0
  61. package/source/jquery.flot.selection.js +552 -0
  62. package/source/jquery.flot.stack.js +220 -0
  63. package/source/jquery.flot.symbol.js +98 -0
  64. package/source/jquery.flot.threshold.js +144 -0
  65. package/source/jquery.flot.time.js +584 -0
  66. package/source/jquery.flot.touch.js +320 -0
  67. package/source/jquery.flot.touchNavigate.js +357 -0
  68. package/source/jquery.flot.uiConstants.js +9 -0
  69. package/source/jquery.js +9473 -0
@@ -0,0 +1,699 @@
1
+ /**
2
+ ## jquery.flot.drawSeries.js
3
+
4
+ This plugin is used by flot for drawing lines, plots, bars or area.
5
+
6
+ ### Public methods
7
+ */
8
+
9
+ import { color } from './jquery.colorhelpers.js';
10
+
11
+ function DrawSeries() {
12
+ function plotLine(datapoints, xoffset, yoffset, axisx, axisy, ctx, steps) {
13
+ var points = datapoints.points,
14
+ ps = datapoints.pointsize,
15
+ prevx = null,
16
+ prevy = null;
17
+ var x1 = 0.0,
18
+ y1 = 0.0,
19
+ x2 = 0.0,
20
+ y2 = 0.0,
21
+ mx = null,
22
+ my = null,
23
+ i = 0;
24
+
25
+ var initPoints = function (i) {
26
+ x1 = points[i - ps];
27
+ y1 = points[i - ps + 1];
28
+ x2 = points[i];
29
+ y2 = points[i + 1];
30
+ };
31
+
32
+ var handleSteps = function () {
33
+ if (mx !== null && my !== null) {
34
+ // if middle point exists, transfer p2 -> p1 and p1 -> mp
35
+ x2 = x1;
36
+ y2 = y1;
37
+ x1 = mx;
38
+ y1 = my;
39
+
40
+ // 'remove' middle point
41
+ mx = null;
42
+ my = null;
43
+
44
+ return true;
45
+ } else if (y1 !== y2 && x1 !== x2) {
46
+ // create a middle point
47
+ y2 = y1;
48
+ mx = x2;
49
+ my = y1;
50
+ }
51
+
52
+ return false;
53
+ };
54
+
55
+ var handleYMinClipping = function () {
56
+ if (y1 <= y2 && y1 < axisy.min) {
57
+ if (y2 < axisy.min) {
58
+ // line segment is outside
59
+ return true;
60
+ }
61
+ // compute new intersection point
62
+ x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
63
+ y1 = axisy.min;
64
+ } else if (y2 <= y1 && y2 < axisy.min) {
65
+ if (y1 < axisy.min) {
66
+ return true;
67
+ }
68
+
69
+ x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
70
+ y2 = axisy.min;
71
+ }
72
+ };
73
+
74
+ var handleYMaxClipping = function () {
75
+ if (y1 >= y2 && y1 > axisy.max) {
76
+ if (y2 > axisy.max) {
77
+ return true;
78
+ }
79
+
80
+ x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
81
+ y1 = axisy.max;
82
+ } else if (y2 >= y1 && y2 > axisy.max) {
83
+ if (y1 > axisy.max) {
84
+ return true;
85
+ }
86
+
87
+ x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
88
+ y2 = axisy.max;
89
+ }
90
+ };
91
+
92
+ var handleXMinClipping = function () {
93
+ if (x1 <= x2 && x1 < axisx.min) {
94
+ if (x2 < axisx.min) {
95
+ return true;
96
+ }
97
+
98
+ y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
99
+ x1 = axisx.min;
100
+ } else if (x2 <= x1 && x2 < axisx.min) {
101
+ if (x1 < axisx.min) {
102
+ return true;
103
+ }
104
+
105
+ y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
106
+ x2 = axisx.min;
107
+ }
108
+ };
109
+
110
+ var handleXMaxClipping = function () {
111
+ if (x1 >= x2 && x1 > axisx.max) {
112
+ if (x2 > axisx.max) {
113
+ return true;
114
+ }
115
+
116
+ y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
117
+ x1 = axisx.max;
118
+ } else if (x2 >= x1 && x2 > axisx.max) {
119
+ if (x1 > axisx.max) {
120
+ return true;
121
+ }
122
+
123
+ y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
124
+ x2 = axisx.max;
125
+ }
126
+ };
127
+
128
+ var drawLine = function () {
129
+ if (x1 !== prevx || y1 !== prevy) {
130
+ ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);
131
+ }
132
+
133
+ prevx = x2;
134
+ prevy = y2;
135
+ ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);
136
+ };
137
+
138
+ ctx.beginPath();
139
+ for (i = ps; i < points.length; i += ps) {
140
+ initPoints(i);
141
+
142
+ if (x1 === null || x2 === null) {
143
+ mx = null;
144
+ my = null;
145
+ continue;
146
+ }
147
+
148
+ if (isNaN(x1) || isNaN(x2) || isNaN(y1) || isNaN(y2)) {
149
+ prevx = null;
150
+ prevy = null;
151
+ continue;
152
+ }
153
+
154
+ if (steps) {
155
+ var hadMiddlePoint = handleSteps();
156
+ if (hadMiddlePoint) {
157
+ // Subtract pointsize from i to have current point p1 handled again.
158
+ i -= ps;
159
+ }
160
+ }
161
+ if (handleYMinClipping()) continue;
162
+ if (handleYMaxClipping()) continue;
163
+ if (handleXMinClipping()) continue;
164
+ if (handleXMaxClipping()) continue;
165
+
166
+ drawLine();
167
+ }
168
+
169
+ // Connects last two points in case middle point exists after the loop.
170
+ if (mx !== null && my !== null) {
171
+ initPoints(i);
172
+ handleSteps();
173
+
174
+ if (!handleYMinClipping() &&
175
+ !handleYMaxClipping() &&
176
+ !handleXMinClipping() &&
177
+ !handleXMaxClipping()) {
178
+ drawLine();
179
+ }
180
+ }
181
+
182
+ ctx.stroke();
183
+ }
184
+
185
+ function plotLineArea(datapoints, axisx, axisy, fillTowards, ctx, steps) {
186
+ var points = datapoints.points,
187
+ ps = datapoints.pointsize,
188
+ bottom = fillTowards > axisy.min ? Math.min(axisy.max, fillTowards) : axisy.min,
189
+ i = 0,
190
+ ypos = 1,
191
+ areaOpen = false,
192
+ segmentStart = 0,
193
+ segmentEnd = 0,
194
+ mx = null,
195
+ my = null;
196
+
197
+ // we process each segment in two turns, first forward
198
+ // direction to sketch out top, then once we hit the
199
+ // end we go backwards to sketch the bottom
200
+ while (true) {
201
+ if (ps > 0 && i > points.length + ps) {
202
+ break;
203
+ }
204
+
205
+ i += ps; // ps is negative if going backwards
206
+
207
+ var x1 = points[i - ps],
208
+ y1 = points[i - ps + ypos],
209
+ x2 = points[i],
210
+ y2 = points[i + ypos];
211
+
212
+ if (ps === -2) {
213
+ /* going backwards and no value for the bottom provided in the series*/
214
+ y1 = y2 = bottom;
215
+ }
216
+
217
+ if (areaOpen) {
218
+ if (ps > 0 && x1 != null && x2 == null) {
219
+ // at turning point
220
+ segmentEnd = i;
221
+ ps = -ps;
222
+ ypos = 2;
223
+ continue;
224
+ }
225
+
226
+ if (ps < 0 && i === segmentStart + ps) {
227
+ // done with the reverse sweep
228
+ ctx.fill();
229
+ areaOpen = false;
230
+ ps = -ps;
231
+ ypos = 1;
232
+ i = segmentStart = segmentEnd + ps;
233
+ continue;
234
+ }
235
+ }
236
+
237
+ if (x1 == null || x2 == null) {
238
+ mx = null;
239
+ my = null;
240
+ continue;
241
+ }
242
+
243
+ if (steps) {
244
+ if (mx !== null && my !== null) {
245
+ // if middle point exists, transfer p2 -> p1 and p1 -> mp
246
+ x2 = x1;
247
+ y2 = y1;
248
+ x1 = mx;
249
+ y1 = my;
250
+
251
+ // 'remove' middle point
252
+ mx = null;
253
+ my = null;
254
+
255
+ // subtract pointsize from i to have current point p1 handled again
256
+ i -= ps;
257
+ } else if (y1 !== y2 && x1 !== x2) {
258
+ // create a middle point
259
+ y2 = y1;
260
+ mx = x2;
261
+ my = y1;
262
+ }
263
+ }
264
+
265
+ // clip x values
266
+
267
+ // clip with xmin
268
+ if (x1 <= x2 && x1 < axisx.min) {
269
+ if (x2 < axisx.min) {
270
+ continue;
271
+ }
272
+
273
+ y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
274
+ x1 = axisx.min;
275
+ } else if (x2 <= x1 && x2 < axisx.min) {
276
+ if (x1 < axisx.min) {
277
+ continue;
278
+ }
279
+
280
+ y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;
281
+ x2 = axisx.min;
282
+ }
283
+
284
+ // clip with xmax
285
+ if (x1 >= x2 && x1 > axisx.max) {
286
+ if (x2 > axisx.max) {
287
+ continue;
288
+ }
289
+
290
+ y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
291
+ x1 = axisx.max;
292
+ } else if (x2 >= x1 && x2 > axisx.max) {
293
+ if (x1 > axisx.max) {
294
+ continue;
295
+ }
296
+
297
+ y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;
298
+ x2 = axisx.max;
299
+ }
300
+
301
+ if (!areaOpen) {
302
+ // open area
303
+ ctx.beginPath();
304
+ ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));
305
+ areaOpen = true;
306
+ }
307
+
308
+ // now first check the case where both is outside
309
+ if (y1 >= axisy.max && y2 >= axisy.max) {
310
+ ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));
311
+ ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));
312
+ continue;
313
+ } else if (y1 <= axisy.min && y2 <= axisy.min) {
314
+ ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));
315
+ ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));
316
+ continue;
317
+ }
318
+
319
+ // else it's a bit more complicated, there might
320
+ // be a flat maxed out rectangle first, then a
321
+ // triangular cutout or reverse; to find these
322
+ // keep track of the current x values
323
+ var x1old = x1,
324
+ x2old = x2;
325
+
326
+ // clip the y values, without shortcutting, we
327
+ // go through all cases in turn
328
+
329
+ // clip with ymin
330
+ if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {
331
+ x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
332
+ y1 = axisy.min;
333
+ } else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {
334
+ x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;
335
+ y2 = axisy.min;
336
+ }
337
+
338
+ // clip with ymax
339
+ if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {
340
+ x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
341
+ y1 = axisy.max;
342
+ } else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {
343
+ x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;
344
+ y2 = axisy.max;
345
+ }
346
+
347
+ // if the x value was changed we got a rectangle
348
+ // to fill
349
+ if (x1 !== x1old) {
350
+ ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));
351
+ // it goes to (x1, y1), but we fill that below
352
+ }
353
+
354
+ // fill triangular section, this sometimes result
355
+ // in redundant points if (x1, y1) hasn't changed
356
+ // from previous line to, but we just ignore that
357
+ ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));
358
+ ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
359
+
360
+ // fill the other rectangle if it's there
361
+ if (x2 !== x2old) {
362
+ ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));
363
+ ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));
364
+ }
365
+ }
366
+ }
367
+
368
+ /**
369
+ - drawSeriesLines(series, ctx, plotOffset, plotWidth, plotHeight, drawSymbol, getColorOrGradient)
370
+
371
+ This function is used for drawing lines or area fill. In case the series has line decimation function
372
+ attached, before starting to draw, as an optimization the points will first be decimated.
373
+
374
+ The series parameter contains the series to be drawn on ctx context. The plotOffset, plotWidth and
375
+ plotHeight are the corresponding parameters of flot used to determine the drawing surface.
376
+ The function getColorOrGradient is used to compute the fill style of lines and area.
377
+ */
378
+ function drawSeriesLines(series, ctx, plotOffset, plotWidth, plotHeight, drawSymbol, getColorOrGradient) {
379
+ ctx.save();
380
+ ctx.translate(plotOffset.left, plotOffset.top);
381
+ ctx.lineJoin = "round";
382
+
383
+ if (series.lines.dashes && ctx.setLineDash) {
384
+ ctx.setLineDash(series.lines.dashes);
385
+ }
386
+
387
+ var datapoints = {
388
+ format: series.datapoints.format,
389
+ points: series.datapoints.points,
390
+ pointsize: series.datapoints.pointsize
391
+ };
392
+
393
+ if (series.decimate) {
394
+ datapoints.points = series.decimate(series, series.xaxis.min, series.xaxis.max, plotWidth, series.yaxis.min, series.yaxis.max, plotHeight);
395
+ }
396
+
397
+ var lw = series.lines.lineWidth;
398
+
399
+ ctx.lineWidth = lw;
400
+ ctx.strokeStyle = series.color;
401
+ var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight, getColorOrGradient);
402
+ if (fillStyle) {
403
+ ctx.fillStyle = fillStyle;
404
+ plotLineArea(datapoints, series.xaxis, series.yaxis, series.lines.fillTowards || 0, ctx, series.lines.steps);
405
+ }
406
+
407
+ if (lw > 0) {
408
+ plotLine(datapoints, 0, 0, series.xaxis, series.yaxis, ctx, series.lines.steps);
409
+ }
410
+
411
+ ctx.restore();
412
+ }
413
+
414
+ /**
415
+ - drawSeriesPoints(series, ctx, plotOffset, plotWidth, plotHeight, drawSymbol, getColorOrGradient)
416
+
417
+ This function is used for drawing points using a given symbol. In case the series has points decimation
418
+ function attached, before starting to draw, as an optimization the points will first be decimated.
419
+
420
+ The series parameter contains the series to be drawn on ctx context. The plotOffset, plotWidth and
421
+ plotHeight are the corresponding parameters of flot used to determine the drawing surface.
422
+ The function drawSymbol is used to compute and draw the symbol chosen for the points.
423
+ */
424
+ function drawSeriesPoints(series, ctx, plotOffset, plotWidth, plotHeight, drawSymbol, getColorOrGradient) {
425
+ function drawCircle(ctx, x, y, radius, shadow, fill) {
426
+ ctx.moveTo(x + radius, y);
427
+ ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);
428
+ }
429
+ drawCircle.fill = true;
430
+ function plotPoints(datapoints, radius, fill, offset, shadow, axisx, axisy, drawSymbolFn) {
431
+ var points = datapoints.points,
432
+ ps = datapoints.pointsize;
433
+
434
+ ctx.beginPath();
435
+ for (var i = 0; i < points.length; i += ps) {
436
+ var x = points[i],
437
+ y = points[i + 1];
438
+ if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) {
439
+ continue;
440
+ }
441
+
442
+ x = axisx.p2c(x);
443
+ y = axisy.p2c(y) + offset;
444
+
445
+ drawSymbolFn(ctx, x, y, radius, shadow, fill);
446
+ }
447
+ if (drawSymbolFn.fill && !shadow) {
448
+ ctx.fill();
449
+ }
450
+ ctx.stroke();
451
+ }
452
+
453
+ ctx.save();
454
+ ctx.translate(plotOffset.left, plotOffset.top);
455
+
456
+ var datapoints = {
457
+ format: series.datapoints.format,
458
+ points: series.datapoints.points,
459
+ pointsize: series.datapoints.pointsize
460
+ };
461
+
462
+ if (series.decimatePoints) {
463
+ datapoints.points = series.decimatePoints(series, series.xaxis.min, series.xaxis.max, plotWidth, series.yaxis.min, series.yaxis.max, plotHeight);
464
+ }
465
+
466
+ var lw = series.points.lineWidth,
467
+ radius = series.points.radius,
468
+ symbol = series.points.symbol,
469
+ drawSymbolFn;
470
+
471
+ if (symbol === 'circle') {
472
+ drawSymbolFn = drawCircle;
473
+ } else if (typeof symbol === 'string' && drawSymbol && drawSymbol[symbol]) {
474
+ drawSymbolFn = drawSymbol[symbol];
475
+ } else if (typeof drawSymbol === 'function') {
476
+ drawSymbolFn = drawSymbol;
477
+ }
478
+
479
+ // If the user sets the line width to 0, we change it to a very
480
+ // small value. A line width of 0 seems to force the default of 1.
481
+
482
+ if (lw === 0) {
483
+ lw = 0.0001;
484
+ }
485
+
486
+ ctx.lineWidth = lw;
487
+ ctx.fillStyle = getFillStyle(series.points, series.color, null, null, getColorOrGradient);
488
+ ctx.strokeStyle = series.color;
489
+ plotPoints(datapoints, radius,
490
+ true, 0, false,
491
+ series.xaxis, series.yaxis, drawSymbolFn);
492
+ ctx.restore();
493
+ }
494
+
495
+ function drawBar(x, y, b, barLeft, barRight, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {
496
+ var left = x + barLeft,
497
+ right = x + barRight,
498
+ bottom = b, top = y,
499
+ drawLeft, drawRight, drawTop, drawBottom = false,
500
+ tmp;
501
+
502
+ drawLeft = drawRight = drawTop = true;
503
+
504
+ // in horizontal mode, we start the bar from the left
505
+ // instead of from the bottom so it appears to be
506
+ // horizontal rather than vertical
507
+ if (horizontal) {
508
+ drawBottom = drawRight = drawTop = true;
509
+ drawLeft = false;
510
+ left = b;
511
+ right = x;
512
+ top = y + barLeft;
513
+ bottom = y + barRight;
514
+
515
+ // account for negative bars
516
+ if (right < left) {
517
+ tmp = right;
518
+ right = left;
519
+ left = tmp;
520
+ drawLeft = true;
521
+ drawRight = false;
522
+ }
523
+ } else {
524
+ drawLeft = drawRight = drawTop = true;
525
+ drawBottom = false;
526
+ left = x + barLeft;
527
+ right = x + barRight;
528
+ bottom = b;
529
+ top = y;
530
+
531
+ // account for negative bars
532
+ if (top < bottom) {
533
+ tmp = top;
534
+ top = bottom;
535
+ bottom = tmp;
536
+ drawBottom = true;
537
+ drawTop = false;
538
+ }
539
+ }
540
+
541
+ // clip
542
+ if (right < axisx.min || left > axisx.max ||
543
+ top < axisy.min || bottom > axisy.max) {
544
+ return;
545
+ }
546
+
547
+ if (left < axisx.min) {
548
+ left = axisx.min;
549
+ drawLeft = false;
550
+ }
551
+
552
+ if (right > axisx.max) {
553
+ right = axisx.max;
554
+ drawRight = false;
555
+ }
556
+
557
+ if (bottom < axisy.min) {
558
+ bottom = axisy.min;
559
+ drawBottom = false;
560
+ }
561
+
562
+ if (top > axisy.max) {
563
+ top = axisy.max;
564
+ drawTop = false;
565
+ }
566
+
567
+ left = axisx.p2c(left);
568
+ bottom = axisy.p2c(bottom);
569
+ right = axisx.p2c(right);
570
+ top = axisy.p2c(top);
571
+
572
+ // fill the bar
573
+ if (fillStyleCallback) {
574
+ c.fillStyle = fillStyleCallback(bottom, top);
575
+ c.fillRect(left, top, right - left, bottom - top)
576
+ }
577
+
578
+ // draw outline
579
+ if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {
580
+ c.beginPath();
581
+
582
+ // FIXME: inline moveTo is buggy with excanvas
583
+ c.moveTo(left, bottom);
584
+ if (drawLeft) {
585
+ c.lineTo(left, top);
586
+ } else {
587
+ c.moveTo(left, top);
588
+ }
589
+
590
+ if (drawTop) {
591
+ c.lineTo(right, top);
592
+ } else {
593
+ c.moveTo(right, top);
594
+ }
595
+
596
+ if (drawRight) {
597
+ c.lineTo(right, bottom);
598
+ } else {
599
+ c.moveTo(right, bottom);
600
+ }
601
+
602
+ if (drawBottom) {
603
+ c.lineTo(left, bottom);
604
+ } else {
605
+ c.moveTo(left, bottom);
606
+ }
607
+
608
+ c.stroke();
609
+ }
610
+ }
611
+
612
+ /**
613
+ - drawSeriesBars(series, ctx, plotOffset, plotWidth, plotHeight, drawSymbol, getColorOrGradient)
614
+
615
+ This function is used for drawing series represented as bars. In case the series has decimation
616
+ function attached, before starting to draw, as an optimization the points will first be decimated.
617
+
618
+ The series parameter contains the series to be drawn on ctx context. The plotOffset, plotWidth and
619
+ plotHeight are the corresponding parameters of flot used to determine the drawing surface.
620
+ The function getColorOrGradient is used to compute the fill style of bars.
621
+ */
622
+ function drawSeriesBars(series, ctx, plotOffset, plotWidth, plotHeight, drawSymbol, getColorOrGradient) {
623
+ function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) {
624
+ var points = datapoints.points,
625
+ ps = datapoints.pointsize,
626
+ fillTowards = series.bars.fillTowards || 0,
627
+ defaultBottom = fillTowards > axisy.min ? Math.min(axisy.max, fillTowards) : axisy.min;
628
+
629
+ for (var i = 0; i < points.length; i += ps) {
630
+ if (points[i] == null) {
631
+ continue;
632
+ }
633
+
634
+ // Use third point as bottom if pointsize is 3
635
+ var bottom = ps === 3 ? points[i + 2] : defaultBottom;
636
+ drawBar(points[i], points[i + 1], bottom, barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
637
+ }
638
+ }
639
+
640
+ ctx.save();
641
+ ctx.translate(plotOffset.left, plotOffset.top);
642
+
643
+ var datapoints = {
644
+ format: series.datapoints.format,
645
+ points: series.datapoints.points,
646
+ pointsize: series.datapoints.pointsize
647
+ };
648
+
649
+ if (series.decimate) {
650
+ datapoints.points = series.decimate(series, series.xaxis.min, series.xaxis.max, plotWidth);
651
+ }
652
+
653
+ ctx.lineWidth = series.bars.lineWidth;
654
+ ctx.strokeStyle = series.color;
655
+
656
+ var barLeft;
657
+ var barWidth = series.bars.barWidth[0] || series.bars.barWidth;
658
+ switch (series.bars.align) {
659
+ case "left":
660
+ barLeft = 0;
661
+ break;
662
+ case "right":
663
+ barLeft = -barWidth;
664
+ break;
665
+ default:
666
+ barLeft = -barWidth / 2;
667
+ }
668
+
669
+ var fillStyleCallback = series.bars.fill ? function(bottom, top) {
670
+ return getFillStyle(series.bars, series.color, bottom, top, getColorOrGradient);
671
+ } : null;
672
+
673
+ plotBars(datapoints, barLeft, barLeft + barWidth, fillStyleCallback, series.xaxis, series.yaxis);
674
+ ctx.restore();
675
+ }
676
+
677
+ function getFillStyle(filloptions, seriesColor, bottom, top, getColorOrGradient) {
678
+ var fill = filloptions.fill;
679
+ if (!fill) {
680
+ return null;
681
+ }
682
+
683
+ if (filloptions.fillColor) {
684
+ return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
685
+ }
686
+
687
+ var c = color.parse(seriesColor);
688
+ c.a = typeof fill === "number" ? fill : 0.4;
689
+ c.normalize();
690
+ return c.toString();
691
+ }
692
+
693
+ this.drawSeriesLines = drawSeriesLines;
694
+ this.drawSeriesPoints = drawSeriesPoints;
695
+ this.drawSeriesBars = drawSeriesBars;
696
+ this.drawBar = drawBar;
697
+ };
698
+
699
+ export var drawSeries = new DrawSeries();