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.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +60 -0
- data/Rakefile +54 -5
- data/app/assets/images/highcharts/earth.svg +432 -0
- data/app/assets/javascripts/highcharts.js +5103 -3147
- data/app/assets/javascripts/highcharts/highcharts-3d.js +930 -277
- data/app/assets/javascripts/highcharts/highcharts-more.js +1374 -249
- data/app/assets/javascripts/highcharts/lib/canvg.js +3073 -0
- data/app/assets/javascripts/highcharts/lib/jspdf.js +16624 -0
- data/app/assets/javascripts/highcharts/lib/rgbcolor.js +299 -0
- data/app/assets/javascripts/highcharts/lib/svg2pdf.js +3488 -0
- data/app/assets/javascripts/highcharts/modules/accessibility.js +654 -212
- data/app/assets/javascripts/highcharts/modules/annotations.js +1552 -274
- data/app/assets/javascripts/highcharts/modules/boost-canvas.js +773 -0
- data/app/assets/javascripts/highcharts/modules/boost.js +636 -210
- data/app/assets/javascripts/highcharts/modules/broken-axis.js +2 -2
- data/app/assets/javascripts/highcharts/modules/bullet.js +364 -0
- data/app/assets/javascripts/highcharts/modules/data.js +766 -38
- data/app/assets/javascripts/highcharts/modules/drag-panes.js +588 -0
- data/app/assets/javascripts/highcharts/modules/drilldown.js +106 -36
- data/app/assets/javascripts/highcharts/modules/export-data.js +597 -0
- data/app/assets/javascripts/highcharts/modules/exporting.js +424 -162
- data/app/assets/javascripts/highcharts/modules/funnel.js +144 -22
- data/app/assets/javascripts/highcharts/modules/gantt.js +1154 -0
- data/app/assets/javascripts/highcharts/modules/grid-axis.js +1 -1
- data/app/assets/javascripts/highcharts/modules/heatmap.js +406 -80
- data/app/assets/javascripts/highcharts/modules/histogram-bellcurve.js +513 -0
- data/app/assets/javascripts/highcharts/modules/item-series.js +126 -0
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +31 -13
- data/app/assets/javascripts/highcharts/modules/offline-exporting.js +179 -57
- data/app/assets/javascripts/highcharts/modules/oldie.js +1378 -0
- data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +8 -6
- data/app/assets/javascripts/highcharts/modules/parallel-coordinates.js +494 -0
- data/app/assets/javascripts/highcharts/modules/pareto.js +275 -0
- data/app/assets/javascripts/highcharts/modules/sankey.js +641 -0
- data/app/assets/javascripts/highcharts/modules/series-label.js +355 -145
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +122 -1
- data/app/assets/javascripts/highcharts/modules/static-scale.js +64 -0
- data/app/assets/javascripts/highcharts/modules/stock.js +1944 -676
- data/app/assets/javascripts/highcharts/modules/streamgraph.js +139 -0
- data/app/assets/javascripts/highcharts/modules/sunburst.js +2403 -0
- data/app/assets/javascripts/highcharts/modules/tilemap.js +1199 -0
- data/app/assets/javascripts/highcharts/modules/treemap.js +538 -134
- data/app/assets/javascripts/highcharts/modules/variable-pie.js +490 -0
- data/app/assets/javascripts/highcharts/modules/variwide.js +283 -0
- data/app/assets/javascripts/highcharts/modules/vector.js +294 -0
- data/app/assets/javascripts/highcharts/modules/windbarb.js +490 -0
- data/app/assets/javascripts/highcharts/modules/wordcloud.js +681 -0
- data/app/assets/javascripts/highcharts/modules/xrange.js +615 -0
- data/app/assets/javascripts/highcharts/themes/avocado.js +54 -0
- data/app/assets/javascripts/highcharts/themes/dark-blue.js +6 -6
- data/app/assets/javascripts/highcharts/themes/dark-green.js +6 -6
- data/app/assets/javascripts/highcharts/themes/dark-unica.js +6 -6
- data/app/assets/javascripts/highcharts/themes/gray.js +14 -10
- data/app/assets/javascripts/highcharts/themes/grid-light.js +6 -6
- data/app/assets/javascripts/highcharts/themes/grid.js +7 -5
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +8 -7
- data/app/assets/javascripts/highcharts/themes/skies.js +15 -9
- data/app/assets/javascripts/highcharts/themes/sunset.js +53 -0
- data/app/assets/stylesheets/highcharts/highcharts.css +802 -0
- data/app/assets/stylesheets/highcharts/highcharts.scss +665 -0
- data/lib/highcharts/version.rb +1 -1
- metadata +31 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS
|
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
|
-
*
|
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,
|
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
|
-
|
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
|
-
|
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
|
106
|
-
intersectLine(x, y + h, x + w, y + h, x1, y1, x2, y2) || // bottom
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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 +
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|
276
|
-
* other series gives more weight. Smaller distance to the actual point
|
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
|
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
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
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
|
-
|
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
|
-
|
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 (
|
345
|
-
|
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
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
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(
|
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
|
-
|
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:
|
420
|
-
|
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
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
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
|
-
|
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
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
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
|
-
|
529
|
-
Math.
|
530
|
-
|
531
|
-
|
532
|
-
|
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
|
-
|
536
|
-
|
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 =
|
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);
|