highcharts-rails 5.0.14 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
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);