highcharts-rails 5.0.14 → 6.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.markdown +60 -0
  3. data/Rakefile +54 -5
  4. data/app/assets/images/highcharts/earth.svg +432 -0
  5. data/app/assets/javascripts/highcharts.js +5103 -3147
  6. data/app/assets/javascripts/highcharts/highcharts-3d.js +930 -277
  7. data/app/assets/javascripts/highcharts/highcharts-more.js +1374 -249
  8. data/app/assets/javascripts/highcharts/lib/canvg.js +3073 -0
  9. data/app/assets/javascripts/highcharts/lib/jspdf.js +16624 -0
  10. data/app/assets/javascripts/highcharts/lib/rgbcolor.js +299 -0
  11. data/app/assets/javascripts/highcharts/lib/svg2pdf.js +3488 -0
  12. data/app/assets/javascripts/highcharts/modules/accessibility.js +654 -212
  13. data/app/assets/javascripts/highcharts/modules/annotations.js +1552 -274
  14. data/app/assets/javascripts/highcharts/modules/boost-canvas.js +773 -0
  15. data/app/assets/javascripts/highcharts/modules/boost.js +636 -210
  16. data/app/assets/javascripts/highcharts/modules/broken-axis.js +2 -2
  17. data/app/assets/javascripts/highcharts/modules/bullet.js +364 -0
  18. data/app/assets/javascripts/highcharts/modules/data.js +766 -38
  19. data/app/assets/javascripts/highcharts/modules/drag-panes.js +588 -0
  20. data/app/assets/javascripts/highcharts/modules/drilldown.js +106 -36
  21. data/app/assets/javascripts/highcharts/modules/export-data.js +597 -0
  22. data/app/assets/javascripts/highcharts/modules/exporting.js +424 -162
  23. data/app/assets/javascripts/highcharts/modules/funnel.js +144 -22
  24. data/app/assets/javascripts/highcharts/modules/gantt.js +1154 -0
  25. data/app/assets/javascripts/highcharts/modules/grid-axis.js +1 -1
  26. data/app/assets/javascripts/highcharts/modules/heatmap.js +406 -80
  27. data/app/assets/javascripts/highcharts/modules/histogram-bellcurve.js +513 -0
  28. data/app/assets/javascripts/highcharts/modules/item-series.js +126 -0
  29. data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +31 -13
  30. data/app/assets/javascripts/highcharts/modules/offline-exporting.js +179 -57
  31. data/app/assets/javascripts/highcharts/modules/oldie.js +1378 -0
  32. data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +8 -6
  33. data/app/assets/javascripts/highcharts/modules/parallel-coordinates.js +494 -0
  34. data/app/assets/javascripts/highcharts/modules/pareto.js +275 -0
  35. data/app/assets/javascripts/highcharts/modules/sankey.js +641 -0
  36. data/app/assets/javascripts/highcharts/modules/series-label.js +355 -145
  37. data/app/assets/javascripts/highcharts/modules/solid-gauge.js +122 -1
  38. data/app/assets/javascripts/highcharts/modules/static-scale.js +64 -0
  39. data/app/assets/javascripts/highcharts/modules/stock.js +1944 -676
  40. data/app/assets/javascripts/highcharts/modules/streamgraph.js +139 -0
  41. data/app/assets/javascripts/highcharts/modules/sunburst.js +2403 -0
  42. data/app/assets/javascripts/highcharts/modules/tilemap.js +1199 -0
  43. data/app/assets/javascripts/highcharts/modules/treemap.js +538 -134
  44. data/app/assets/javascripts/highcharts/modules/variable-pie.js +490 -0
  45. data/app/assets/javascripts/highcharts/modules/variwide.js +283 -0
  46. data/app/assets/javascripts/highcharts/modules/vector.js +294 -0
  47. data/app/assets/javascripts/highcharts/modules/windbarb.js +490 -0
  48. data/app/assets/javascripts/highcharts/modules/wordcloud.js +681 -0
  49. data/app/assets/javascripts/highcharts/modules/xrange.js +615 -0
  50. data/app/assets/javascripts/highcharts/themes/avocado.js +54 -0
  51. data/app/assets/javascripts/highcharts/themes/dark-blue.js +6 -6
  52. data/app/assets/javascripts/highcharts/themes/dark-green.js +6 -6
  53. data/app/assets/javascripts/highcharts/themes/dark-unica.js +6 -6
  54. data/app/assets/javascripts/highcharts/themes/gray.js +14 -10
  55. data/app/assets/javascripts/highcharts/themes/grid-light.js +6 -6
  56. data/app/assets/javascripts/highcharts/themes/grid.js +7 -5
  57. data/app/assets/javascripts/highcharts/themes/sand-signika.js +8 -7
  58. data/app/assets/javascripts/highcharts/themes/skies.js +15 -9
  59. data/app/assets/javascripts/highcharts/themes/sunset.js +53 -0
  60. data/app/assets/stylesheets/highcharts/highcharts.css +802 -0
  61. data/app/assets/stylesheets/highcharts/highcharts.scss +665 -0
  62. data/lib/highcharts/version.rb +1 -1
  63. metadata +31 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.14 (2017-07-28)
2
+ * @license Highcharts JS v6.0.0 (2017-10-04)
3
3
  *
4
4
  * (c) 2009-2017 Torstein Honsi
5
5
  *
@@ -20,11 +20,10 @@
20
20
  * License: www.highcharts.com/license
21
21
  */
22
22
  /**
23
- * EXPERIMENTAL Highcharts module to place labels next to a series in a natural position.
23
+ * Highcharts module to place labels next to a series in a natural position.
24
24
  *
25
25
  * TODO:
26
26
  * - add column support (box collision detection, boxesToAvoid logic)
27
- * - other series types, area etc.
28
27
  * - avoid data labels, when data labels above, show series label below.
29
28
  * - add more options (connector, format, formatter)
30
29
  *
@@ -40,41 +39,92 @@
40
39
  each = H.each,
41
40
  extend = H.extend,
42
41
  isNumber = H.isNumber,
42
+ pick = H.pick,
43
43
  Series = H.Series,
44
44
  SVGRenderer = H.SVGRenderer,
45
45
  Chart = H.Chart;
46
46
 
47
47
  H.setOptions({
48
+ /**
49
+ * @optionparent plotOptions
50
+ */
48
51
  plotOptions: {
49
52
  series: {
50
-
51
53
  /**
54
+ * Series labels are placed as close to the series as possible in a
55
+ * natural way, seeking to avoid other series. The goal of this
56
+ * feature is to make the chart more easily readable, like if a
57
+ * human designer placed the labels in the optimal position.
58
+ *
59
+ * The series labels currently work with series types having a
60
+ * `graph` or an `area`.
61
+ *
62
+ * Requires the `series-label.js` module.
63
+ *
64
+ * @sample highcharts/series-label/line-chart
65
+ * Line chart
66
+ * @sample highcharts/demo/streamgraph
67
+ * Stream graph
68
+ * @sample highcharts/series-label/stock-chart
69
+ * Stock chart
70
+ * @since 6.0.0
71
+ * @product highcharts highstock
52
72
  */
53
73
  label: {
54
-
55
74
  /**
75
+ * Enable the series label per series.
56
76
  */
57
77
  enabled: true,
58
- // Allow labels to be placed distant to the graph if necessary, and
59
- // draw a connector line to the graph
60
-
61
78
  /**
79
+ * Allow labels to be placed distant to the graph if necessary,
80
+ * and draw a connector line to the graph.
62
81
  */
63
82
  connectorAllowed: true,
64
-
65
83
  /**
84
+ * If the label is closer than this to a neighbour graph, draw a
85
+ * connector.
66
86
  */
67
- connectorNeighbourDistance: 24, // If the label is closer than this to a neighbour graph, draw a connector
68
-
87
+ connectorNeighbourDistance: 24,
88
+ /**
89
+ * For area-like series, allow the font size to vary so that
90
+ * small areas get a smaller font size. The default applies this
91
+ * effect to area-like series but not line-like series.
92
+ *
93
+ * @type {Number}
94
+ */
95
+ minFontSize: null,
96
+ /**
97
+ * For area-like series, allow the font size to vary so that
98
+ * small areas get a smaller font size. The default applies this
99
+ * effect to area-like series but not line-like series.
100
+ *
101
+ * @type {Number}
102
+ */
103
+ maxFontSize: null,
69
104
  /**
105
+ * Draw the label on the area of an area series. By default it
106
+ * is drawn on the area. Set it to `false` to draw it next to
107
+ * the graph instead.
108
+ *
109
+ * @type {Boolean}
70
110
  */
71
- styles: {
111
+ onArea: null,
72
112
 
73
- /**
74
- */
113
+ /**
114
+ * Styles for the series label. The color defaults to the series
115
+ * color, or a contrast color if `onArea`.
116
+ */
117
+ style: {
75
118
  fontWeight: 'bold'
76
- }
77
- // boxesToAvoid: []
119
+ },
120
+
121
+ /**
122
+ * An array of boxes to avoid when laying out the labels. Each
123
+ * item has a `left`, `right`, `top` and `bottom` property.
124
+ *
125
+ * @type {Array.<Object>}
126
+ */
127
+ boxesToAvoid: []
78
128
  }
79
129
  }
80
130
  }
@@ -102,8 +152,8 @@
102
152
  function boxIntersectLine(x, y, w, h, x1, y1, x2, y2) {
103
153
  return (
104
154
  intersectLine(x, y, x + w, y, x1, y1, x2, y2) || // top of label
105
- intersectLine(x + w, y, x + w, y + h, x1, y1, x2, y2) || // right of label
106
- intersectLine(x, y + h, x + w, y + h, x1, y1, x2, y2) || // bottom of label
155
+ intersectLine(x + w, y, x + w, y + h, x1, y1, x2, y2) || // right
156
+ intersectLine(x, y + h, x + w, y + h, x1, y1, x2, y2) || // bottom
107
157
  intersectLine(x, y, x, y + h, x1, y1, x2, y2) // left of label
108
158
  );
109
159
  }
@@ -156,6 +206,11 @@
156
206
  * interpolated positions.
157
207
  */
158
208
  Series.prototype.getPointsOnGraph = function() {
209
+
210
+ if (!this.xAxis && !this.yAxis) {
211
+ return;
212
+ }
213
+
159
214
  var distance = 16,
160
215
  points = this.points,
161
216
  point,
@@ -172,12 +227,18 @@
172
227
  graph = this.graph || this.area,
173
228
  node = graph.element,
174
229
  inverted = this.chart.inverted,
175
- paneLeft = inverted ? this.yAxis.pos : this.xAxis.pos,
176
- paneTop = inverted ? this.xAxis.pos : this.yAxis.pos;
177
-
178
- // For splines, get the point at length (possible caveat: peaks are not correctly detected)
179
- if (this.getPointSpline && node.getPointAtLength) {
180
- // If it is animating towards a path definition, use that briefly, and reset
230
+ xAxis = this.xAxis,
231
+ yAxis = this.yAxis,
232
+ paneLeft = inverted ? yAxis.pos : xAxis.pos,
233
+ paneTop = inverted ? xAxis.pos : yAxis.pos,
234
+ onArea = pick(this.options.label.onArea, !!this.area),
235
+ translatedThreshold = yAxis.getThreshold(this.options.threshold);
236
+
237
+ // For splines, get the point at length (possible caveat: peaks are not
238
+ // correctly detected)
239
+ if (this.getPointSpline && node.getPointAtLength && !onArea) {
240
+ // If it is animating towards a path definition, use that briefly, and
241
+ // reset
181
242
  if (graph.toD) {
182
243
  d = graph.attr('d');
183
244
  graph.attr({
@@ -216,6 +277,13 @@
216
277
  // Absolute coordinates so we can compare different panes
217
278
  point.chartX = paneLeft + point.plotX;
218
279
  point.chartY = paneTop + point.plotY;
280
+ if (onArea) {
281
+ // Vertically centered inside area
282
+ point.chartCenterY = paneTop + (
283
+ point.plotY +
284
+ pick(point.yBottom, translatedThreshold)
285
+ ) / 2;
286
+ }
219
287
 
220
288
  // Add interpolated points
221
289
  if (i > 0) {
@@ -228,10 +296,17 @@
228
296
 
229
297
  for (j = 1; j < n; j += 1) {
230
298
  interpolated.push({
231
- chartX: last.chartX + (point.chartX - last.chartX) * (j / n),
232
- chartY: last.chartY + (point.chartY - last.chartY) * (j / n),
233
- plotX: last.plotX + (point.plotX - last.plotX) * (j / n),
234
- plotY: last.plotY + (point.plotY - last.plotY) * (j / n)
299
+ chartX: last.chartX +
300
+ (point.chartX - last.chartX) * (j / n),
301
+ chartY: last.chartY +
302
+ (point.chartY - last.chartY) * (j / n),
303
+ chartCenterY: last.chartCenterY +
304
+ (point.chartCenterY - last.chartCenterY) *
305
+ (j / n),
306
+ plotX: last.plotX +
307
+ (point.plotX - last.plotX) * (j / n),
308
+ plotY: last.plotY +
309
+ (point.plotY - last.plotY) * (j / n)
235
310
  });
236
311
  }
237
312
  }
@@ -243,9 +318,30 @@
243
318
  }
244
319
  }
245
320
  }
321
+
322
+ // Get the bounding box so we can do a quick check first if the bounding
323
+ // boxes overlap.
324
+ /*
325
+ interpolated.bBox = node.getBBox();
326
+ interpolated.bBox.x += paneLeft;
327
+ interpolated.bBox.y += paneTop;
328
+ */
329
+
246
330
  return interpolated;
247
331
  };
248
332
 
333
+ /**
334
+ * Overridable function to return series-specific font sizes for the labels. By
335
+ * default it returns bigger font sizes for series with the greater sum of y
336
+ * values.
337
+ */
338
+ Series.prototype.labelFontSize = function(minFontSize, maxFontSize) {
339
+ return minFontSize + (
340
+ (this.sum / this.chart.labelSeriesMaxSum) *
341
+ (maxFontSize - minFontSize)
342
+ ) + 'px';
343
+ };
344
+
249
345
  /**
250
346
  * Check whether a proposed label position is clear of other elements
251
347
  */
@@ -255,12 +351,14 @@
255
351
  dist,
256
352
  connectorPoint,
257
353
  connectorEnabled = this.options.label.connectorAllowed,
258
-
354
+ onArea = pick(this.options.label.onArea, !!this.area),
259
355
  chart = this.chart,
260
356
  series,
261
357
  points,
262
358
  leastDistance = 16,
263
359
  withinRange,
360
+ xDist,
361
+ yDist,
264
362
  i,
265
363
  j;
266
364
 
@@ -272,9 +370,9 @@
272
370
  }
273
371
 
274
372
  /**
275
- * Get the weight in order to determine the ideal position. Larger distance to
276
- * other series gives more weight. Smaller distance to the actual point (connector points only)
277
- * gives more weight.
373
+ * Get the weight in order to determine the ideal position. Larger distance
374
+ * to other series gives more weight. Smaller distance to the actual point
375
+ * (connector points only) gives more weight.
278
376
  */
279
377
  function getWeight(distToOthersSquared, distToPointSquared) {
280
378
  return distToOthersSquared - distToPointSquared;
@@ -292,64 +390,99 @@
292
390
  }
293
391
  }
294
392
 
295
- // For each position, check if the lines around the label intersect with any of the
296
- // graphs
393
+ // For each position, check if the lines around the label intersect with any
394
+ // of the graphs.
297
395
  for (i = 0; i < chart.series.length; i += 1) {
298
396
  series = chart.series[i];
299
397
  points = series.interpolatedPoints;
300
398
  if (series.visible && points) {
301
399
  for (j = 1; j < points.length; j += 1) {
302
- // If any of the box sides intersect with the line, return
303
- if (boxIntersectLine(
304
- x,
305
- y,
306
- bBox.width,
307
- bBox.height,
308
- points[j - 1].chartX,
309
- points[j - 1].chartY,
310
- points[j].chartX,
311
- points[j].chartY
312
- )) {
313
- return false;
314
- }
315
400
 
316
- // But if it is too far away (a padded box doesn't intersect), also return
317
- if (this === series && !withinRange && checkDistance) {
318
- withinRange = boxIntersectLine(
319
- x - leastDistance,
320
- y - leastDistance,
321
- bBox.width + 2 * leastDistance,
322
- bBox.height + 2 * leastDistance,
323
- points[j - 1].chartX,
324
- points[j - 1].chartY,
325
- points[j].chartX,
326
- points[j].chartY
327
- );
401
+ if (
402
+ // To avoid processing, only check intersection if the X
403
+ // values are close to the box.
404
+ points[j].chartX >= x - leastDistance &&
405
+ points[j - 1].chartX <= x + bBox.width + leastDistance
406
+ ) {
407
+ // If any of the box sides intersect with the line, return.
408
+ if (boxIntersectLine(
409
+ x,
410
+ y,
411
+ bBox.width,
412
+ bBox.height,
413
+ points[j - 1].chartX,
414
+ points[j - 1].chartY,
415
+ points[j].chartX,
416
+ points[j].chartY
417
+ )) {
418
+ return false;
419
+ }
420
+
421
+ // But if it is too far away (a padded box doesn't
422
+ // intersect), also return.
423
+ if (this === series && !withinRange && checkDistance) {
424
+ withinRange = boxIntersectLine(
425
+ x - leastDistance,
426
+ y - leastDistance,
427
+ bBox.width + 2 * leastDistance,
428
+ bBox.height + 2 * leastDistance,
429
+ points[j - 1].chartX,
430
+ points[j - 1].chartY,
431
+ points[j].chartX,
432
+ points[j].chartY
433
+ );
434
+ }
328
435
  }
329
436
 
330
- // Find the squared distance from the center of the label
331
- if (this !== series) {
437
+ // Find the squared distance from the center of the label. On
438
+ // area series, avoid its own graph.
439
+ if (
440
+ (connectorEnabled || withinRange) &&
441
+ (this !== series || onArea)
442
+ ) {
443
+ xDist = x + bBox.width / 2 - points[j].chartX;
444
+ yDist = y + bBox.height / 2 - points[j].chartY;
332
445
  distToOthersSquared = Math.min(
333
446
  distToOthersSquared,
334
- Math.pow(x + bBox.width / 2 - points[j].chartX, 2) + Math.pow(y + bBox.height / 2 - points[j].chartY, 2),
335
- Math.pow(x - points[j].chartX, 2) + Math.pow(y - points[j].chartY, 2),
336
- Math.pow(x + bBox.width - points[j].chartX, 2) + Math.pow(y - points[j].chartY, 2),
337
- Math.pow(x + bBox.width - points[j].chartX, 2) + Math.pow(y + bBox.height - points[j].chartY, 2),
338
- Math.pow(x - points[j].chartX, 2) + Math.pow(y + bBox.height - points[j].chartY, 2)
447
+ xDist * xDist + yDist * yDist
339
448
  );
340
449
  }
341
450
  }
342
451
 
343
452
  // Do we need a connector?
344
- if (connectorEnabled && this === series && ((checkDistance && !withinRange) ||
345
- distToOthersSquared < Math.pow(this.options.label.connectorNeighbourDistance, 2))) {
453
+ if (!onArea &&
454
+ connectorEnabled &&
455
+ this === series &&
456
+ (
457
+ (checkDistance && !withinRange) ||
458
+ distToOthersSquared < Math.pow(
459
+ this.options.label.connectorNeighbourDistance,
460
+ 2
461
+ )
462
+ )
463
+ ) {
346
464
  for (j = 1; j < points.length; j += 1) {
347
465
  dist = Math.min(
348
- Math.pow(x + bBox.width / 2 - points[j].chartX, 2) + Math.pow(y + bBox.height / 2 - points[j].chartY, 2),
349
- Math.pow(x - points[j].chartX, 2) + Math.pow(y - points[j].chartY, 2),
350
- Math.pow(x + bBox.width - points[j].chartX, 2) + Math.pow(y - points[j].chartY, 2),
351
- Math.pow(x + bBox.width - points[j].chartX, 2) + Math.pow(y + bBox.height - points[j].chartY, 2),
352
- Math.pow(x - points[j].chartX, 2) + Math.pow(y + bBox.height - points[j].chartY, 2)
466
+ (
467
+ Math.pow(x + bBox.width / 2 - points[j].chartX, 2) +
468
+ Math.pow(y + bBox.height / 2 - points[j].chartY, 2)
469
+ ),
470
+ (
471
+ Math.pow(x - points[j].chartX, 2) +
472
+ Math.pow(y - points[j].chartY, 2)
473
+ ),
474
+ (
475
+ Math.pow(x + bBox.width - points[j].chartX, 2) +
476
+ Math.pow(y - points[j].chartY, 2)
477
+ ),
478
+ (
479
+ Math.pow(x + bBox.width - points[j].chartX, 2) +
480
+ Math.pow(y + bBox.height - points[j].chartY, 2)
481
+ ),
482
+ (
483
+ Math.pow(x - points[j].chartX, 2) +
484
+ Math.pow(y + bBox.height - points[j].chartY, 2)
485
+ )
353
486
  );
354
487
  if (dist < distToPointSquared) {
355
488
  distToPointSquared = dist;
@@ -364,7 +497,10 @@
364
497
  return !checkDistance || withinRange ? {
365
498
  x: x,
366
499
  y: y,
367
- weight: getWeight(distToOthersSquared, connectorPoint ? distToPointSquared : 0),
500
+ weight: getWeight(
501
+ distToOthersSquared,
502
+ connectorPoint ? distToPointSquared : 0
503
+ ),
368
504
  connectorPoint: connectorPoint
369
505
  } : false;
370
506
 
@@ -376,6 +512,9 @@
376
512
  * account when placing the labels.
377
513
  */
378
514
  Chart.prototype.drawSeriesLabels = function() {
515
+
516
+ // console.time('drawSeriesLabels');
517
+
379
518
  var chart = this,
380
519
  labelSeries = this.labelSeries;
381
520
 
@@ -391,6 +530,11 @@
391
530
  });
392
531
 
393
532
  each(chart.series, function(series) {
533
+
534
+ if (!series.xAxis && !series.yAxis) {
535
+ return;
536
+ }
537
+
394
538
  var bBox,
395
539
  x,
396
540
  y,
@@ -398,13 +542,17 @@
398
542
  clearPoint,
399
543
  i,
400
544
  best,
545
+ labelOptions = series.options.label,
401
546
  inverted = chart.inverted,
402
547
  paneLeft = inverted ? series.yAxis.pos : series.xAxis.pos,
403
548
  paneTop = inverted ? series.xAxis.pos : series.yAxis.pos,
404
549
  paneWidth = chart.inverted ? series.yAxis.len : series.xAxis.len,
405
550
  paneHeight = chart.inverted ? series.xAxis.len : series.yAxis.len,
406
551
  points = series.interpolatedPoints,
407
- label = series.labelBySeries;
552
+ onArea = pick(labelOptions.onArea, !!series.area),
553
+ label = series.labelBySeries,
554
+ minFontSize = labelOptions.minFontSize,
555
+ maxFontSize = labelOptions.maxFontSize;
408
556
 
409
557
  function insidePane(x, y, bBox) {
410
558
  return x > paneLeft && x <= paneLeft + paneWidth - bBox.width &&
@@ -416,13 +564,24 @@
416
564
  series.labelBySeries = label = chart.renderer
417
565
  .label(series.name, 0, -9999, 'connector')
418
566
  .css(extend({
419
- color: series.color
420
- }, series.options.label.styles))
567
+ color: onArea ?
568
+ chart.renderer.getContrast(series.color) : series.color
569
+ }, series.options.label.style));
570
+
571
+ // Adapt label sizes to the sum of the data
572
+ if (minFontSize && maxFontSize) {
573
+ label.css({
574
+ fontSize: series.labelFontSize(minFontSize, maxFontSize)
575
+ });
576
+ }
577
+
578
+ label
421
579
  .attr({
422
580
  padding: 0,
423
- opacity: 0,
581
+ opacity: chart.renderer.forExport ? 1 : 0,
424
582
  stroke: series.color,
425
- 'stroke-width': 1
583
+ 'stroke-width': 1,
584
+ zIndex: 3
426
585
  })
427
586
  .add(series.group)
428
587
  .animate({
@@ -439,66 +598,85 @@
439
598
  // of chart
440
599
  for (i = points.length - 1; i > 0; i -= 1) {
441
600
 
442
- // Right - up
443
- x = points[i].chartX + labelDistance;
444
- y = points[i].chartY - bBox.height - labelDistance;
445
- if (insidePane(x, y, bBox)) {
446
- best = series.checkClearPoint(
447
- x,
448
- y,
449
- bBox
450
- );
451
- }
452
- if (best) {
453
- results.push(best);
454
- }
601
+ if (onArea) {
602
+
603
+ // Centered
604
+ x = points[i].chartX - bBox.width / 2;
605
+ y = points[i].chartCenterY - bBox.height / 2;
606
+ if (insidePane(x, y, bBox)) {
607
+ best = series.checkClearPoint(
608
+ x,
609
+ y,
610
+ bBox
611
+ );
612
+ }
613
+ if (best) {
614
+ results.push(best);
615
+ }
455
616
 
456
- // Right - down
457
- x = points[i].chartX + labelDistance;
458
- y = points[i].chartY + labelDistance;
459
- if (insidePane(x, y, bBox)) {
460
- best = series.checkClearPoint(
461
- x,
462
- y,
463
- bBox
464
- );
465
- }
466
- if (best) {
467
- results.push(best);
468
- }
469
617
 
470
- // Left - down
471
- x = points[i].chartX - bBox.width - labelDistance;
472
- y = points[i].chartY + labelDistance;
473
- if (insidePane(x, y, bBox)) {
474
- best = series.checkClearPoint(
475
- x,
476
- y,
477
- bBox
478
- );
479
- }
480
- if (best) {
481
- results.push(best);
482
- }
618
+ } else {
483
619
 
484
- // Left - up
485
- x = points[i].chartX - bBox.width - labelDistance;
486
- y = points[i].chartY - bBox.height - labelDistance;
487
- if (insidePane(x, y, bBox)) {
488
- best = series.checkClearPoint(
489
- x,
490
- y,
491
- bBox
492
- );
493
- }
494
- if (best) {
495
- results.push(best);
496
- }
620
+ // Right - up
621
+ x = points[i].chartX + labelDistance;
622
+ y = points[i].chartY - bBox.height - labelDistance;
623
+ if (insidePane(x, y, bBox)) {
624
+ best = series.checkClearPoint(
625
+ x,
626
+ y,
627
+ bBox
628
+ );
629
+ }
630
+ if (best) {
631
+ results.push(best);
632
+ }
633
+
634
+ // Right - down
635
+ x = points[i].chartX + labelDistance;
636
+ y = points[i].chartY + labelDistance;
637
+ if (insidePane(x, y, bBox)) {
638
+ best = series.checkClearPoint(
639
+ x,
640
+ y,
641
+ bBox
642
+ );
643
+ }
644
+ if (best) {
645
+ results.push(best);
646
+ }
647
+
648
+ // Left - down
649
+ x = points[i].chartX - bBox.width - labelDistance;
650
+ y = points[i].chartY + labelDistance;
651
+ if (insidePane(x, y, bBox)) {
652
+ best = series.checkClearPoint(
653
+ x,
654
+ y,
655
+ bBox
656
+ );
657
+ }
658
+ if (best) {
659
+ results.push(best);
660
+ }
497
661
 
662
+ // Left - up
663
+ x = points[i].chartX - bBox.width - labelDistance;
664
+ y = points[i].chartY - bBox.height - labelDistance;
665
+ if (insidePane(x, y, bBox)) {
666
+ best = series.checkClearPoint(
667
+ x,
668
+ y,
669
+ bBox
670
+ );
671
+ }
672
+ if (best) {
673
+ results.push(best);
674
+ }
675
+ }
498
676
  }
499
677
 
500
678
  // Brute force, try all positions on the chart in a 16x16 grid
501
- if (!results.length) {
679
+ if (!results.length && !onArea) {
502
680
  for (x = paneLeft + paneWidth - bBox.width; x >= paneLeft; x -= 16) {
503
681
  for (y = paneTop; y < paneTop + paneHeight - bBox.height; y += 16) {
504
682
  clearPoint = series.checkClearPoint(x, y, bBox, true);
@@ -525,19 +703,39 @@
525
703
  });
526
704
 
527
705
  // Move it if needed
528
- if (Math.round(best.x) !== Math.round(label.x) ||
529
- Math.round(best.y) !== Math.round(label.y)) {
530
- series.labelBySeries
531
- .attr({
532
- opacity: 0,
706
+ var dist = Math.sqrt(
707
+ Math.pow(Math.abs(best.x - label.x), 2),
708
+ Math.pow(Math.abs(best.y - label.y), 2)
709
+ );
710
+
711
+ if (dist) {
712
+
713
+ // Move fast and fade in - pure animation movement is
714
+ // distractive...
715
+ var attr = {
716
+ opacity: chart.renderer.forExport ? 1 : 0,
533
717
  x: best.x - paneLeft,
534
- y: best.y - paneTop,
535
- anchorX: best.connectorPoint && best.connectorPoint.plotX,
536
- anchorY: best.connectorPoint && best.connectorPoint.plotY
537
- })
538
- .animate({
718
+ y: best.y - paneTop
719
+ },
720
+ anim = {
539
721
  opacity: 1
540
- });
722
+ };
723
+ // ... unless we're just moving a short distance
724
+ if (dist <= 10) {
725
+ anim = {
726
+ x: attr.x,
727
+ y: attr.y
728
+ };
729
+ attr = {};
730
+ }
731
+ series.labelBySeries
732
+ .attr(extend(attr, {
733
+ anchorX: best.connectorPoint &&
734
+ best.connectorPoint.plotX,
735
+ anchorY: best.connectorPoint &&
736
+ best.connectorPoint.plotY
737
+ }))
738
+ .animate(anim);
541
739
 
542
740
  // Record closest point to stick to for sync redraw
543
741
  series.options.kdNow = true;
@@ -559,6 +757,7 @@
559
757
  }
560
758
  }
561
759
  });
760
+ // console.timeEnd('drawSeriesLabels');
562
761
  };
563
762
 
564
763
  /**
@@ -576,6 +775,7 @@
576
775
  proceed.apply(chart, [].slice.call(arguments, 1));
577
776
 
578
777
  chart.labelSeries = [];
778
+ chart.labelSeriesMaxSum = 0;
579
779
 
580
780
  clearTimeout(chart.seriesLabelTimer);
581
781
 
@@ -588,6 +788,16 @@
588
788
  if (options.enabled && series.visible && (series.graph || series.area)) {
589
789
  chart.labelSeries.push(series);
590
790
 
791
+ if (options.minFontSize && options.maxFontSize) {
792
+ series.sum = H.reduce(series.yData, function(pv, cv) {
793
+ return (pv || 0) + (cv || 0);
794
+ }, 0);
795
+ chart.labelSeriesMaxSum = Math.max(
796
+ chart.labelSeriesMaxSum,
797
+ series.sum
798
+ );
799
+ }
800
+
591
801
  // The labels are processing heavy, wait until the animation is done
592
802
  if (initial) {
593
803
  delay = Math.max(
@@ -612,9 +822,9 @@
612
822
  }
613
823
  });
614
824
 
615
- chart.seriesLabelTimer = setTimeout(function() {
825
+ chart.seriesLabelTimer = H.syncTimeout(function() {
616
826
  chart.drawSeriesLabels();
617
- }, delay);
827
+ }, chart.renderer.forExport ? 0 : delay);
618
828
 
619
829
  }
620
830
  wrap(Chart.prototype, 'render', drawLabels);