highcharts_rails 0.1.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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +106 -0
  9. data/Rakefile +6 -0
  10. data/highcharts_rails.gemspec +27 -0
  11. data/lib/highcharts_rails/version.rb +3 -0
  12. data/lib/highcharts_rails.rb +8 -0
  13. data/vendor/assets/javascripts/highcharts-3d.src.js +2139 -0
  14. data/vendor/assets/javascripts/highcharts-more.src.js +2982 -0
  15. data/vendor/assets/javascripts/highcharts.src.js +22947 -0
  16. data/vendor/assets/javascripts/js/highcharts-3d.src.js +2085 -0
  17. data/vendor/assets/javascripts/js/highcharts-more.src.js +2820 -0
  18. data/vendor/assets/javascripts/js/highcharts.src.js +20917 -0
  19. data/vendor/assets/javascripts/js/modules/accessibility.src.js +1072 -0
  20. data/vendor/assets/javascripts/js/modules/annotations.src.js +408 -0
  21. data/vendor/assets/javascripts/js/modules/boost.src.js +652 -0
  22. data/vendor/assets/javascripts/js/modules/broken-axis.src.js +338 -0
  23. data/vendor/assets/javascripts/js/modules/data.src.js +981 -0
  24. data/vendor/assets/javascripts/js/modules/drilldown.src.js +756 -0
  25. data/vendor/assets/javascripts/js/modules/exporting.src.js +953 -0
  26. data/vendor/assets/javascripts/js/modules/funnel.src.js +290 -0
  27. data/vendor/assets/javascripts/js/modules/gantt.src.js +791 -0
  28. data/vendor/assets/javascripts/js/modules/grid-axis.src.js +545 -0
  29. data/vendor/assets/javascripts/js/modules/heatmap.src.js +798 -0
  30. data/vendor/assets/javascripts/js/modules/no-data-to-display.src.js +150 -0
  31. data/vendor/assets/javascripts/js/modules/offline-exporting.src.js +492 -0
  32. data/vendor/assets/javascripts/js/modules/overlapping-datalabels.src.js +164 -0
  33. data/vendor/assets/javascripts/js/modules/series-label.src.js +606 -0
  34. data/vendor/assets/javascripts/js/modules/solid-gauge.src.js +305 -0
  35. data/vendor/assets/javascripts/js/modules/treemap.src.js +881 -0
  36. data/vendor/assets/javascripts/js/modules/xrange-series.src.js +254 -0
  37. data/vendor/assets/javascripts/js/themes/dark-blue.js +317 -0
  38. data/vendor/assets/javascripts/js/themes/dark-green.js +314 -0
  39. data/vendor/assets/javascripts/js/themes/dark-unica.js +243 -0
  40. data/vendor/assets/javascripts/js/themes/gray.js +326 -0
  41. data/vendor/assets/javascripts/js/themes/grid-light.js +99 -0
  42. data/vendor/assets/javascripts/js/themes/grid.js +131 -0
  43. data/vendor/assets/javascripts/js/themes/sand-signika.js +129 -0
  44. data/vendor/assets/javascripts/js/themes/skies.js +112 -0
  45. data/vendor/assets/javascripts/lib/canvg.src.js +3073 -0
  46. data/vendor/assets/javascripts/lib/jspdf.src.js +3031 -0
  47. data/vendor/assets/javascripts/lib/rgbcolor.src.js +299 -0
  48. data/vendor/assets/javascripts/lib/svg2pdf.src.js +1451 -0
  49. data/vendor/assets/javascripts/modules/accessibility.src.js +1072 -0
  50. data/vendor/assets/javascripts/modules/annotations.src.js +408 -0
  51. data/vendor/assets/javascripts/modules/boost.src.js +652 -0
  52. data/vendor/assets/javascripts/modules/broken-axis.src.js +338 -0
  53. data/vendor/assets/javascripts/modules/data.src.js +981 -0
  54. data/vendor/assets/javascripts/modules/drilldown.src.js +797 -0
  55. data/vendor/assets/javascripts/modules/exporting.src.js +882 -0
  56. data/vendor/assets/javascripts/modules/funnel.src.js +304 -0
  57. data/vendor/assets/javascripts/modules/gantt.src.js +815 -0
  58. data/vendor/assets/javascripts/modules/grid-axis.src.js +547 -0
  59. data/vendor/assets/javascripts/modules/heatmap.src.js +810 -0
  60. data/vendor/assets/javascripts/modules/no-data-to-display.src.js +161 -0
  61. data/vendor/assets/javascripts/modules/offline-exporting.src.js +492 -0
  62. data/vendor/assets/javascripts/modules/overlapping-datalabels.src.js +164 -0
  63. data/vendor/assets/javascripts/modules/series-label.src.js +606 -0
  64. data/vendor/assets/javascripts/modules/solid-gauge.src.js +316 -0
  65. data/vendor/assets/javascripts/modules/treemap.src.js +935 -0
  66. data/vendor/assets/javascripts/modules/xrange-series.src.js +276 -0
  67. data/vendor/assets/javascripts/themes/dark-blue.js +317 -0
  68. data/vendor/assets/javascripts/themes/dark-green.js +314 -0
  69. data/vendor/assets/javascripts/themes/dark-unica.js +243 -0
  70. data/vendor/assets/javascripts/themes/gray.js +326 -0
  71. data/vendor/assets/javascripts/themes/grid-light.js +99 -0
  72. data/vendor/assets/javascripts/themes/grid.js +131 -0
  73. data/vendor/assets/javascripts/themes/sand-signika.js +129 -0
  74. data/vendor/assets/javascripts/themes/skies.js +112 -0
  75. data/vendor/assets/stylesheets/highcharts.scss +610 -0
  76. metadata +161 -0
@@ -0,0 +1,2085 @@
1
+ /**
2
+ * @license Highcharts JS v5.0.6 (2016-12-07)
3
+ *
4
+ * 3D features for Highcharts JS
5
+ *
6
+ * @license: www.highcharts.com/license
7
+ */
8
+ (function(factory) {
9
+ if (typeof module === 'object' && module.exports) {
10
+ module.exports = factory;
11
+ } else {
12
+ factory(Highcharts);
13
+ }
14
+ }(function(Highcharts) {
15
+ (function(H) {
16
+ /**
17
+ * (c) 2010-2016 Torstein Honsi
18
+ *
19
+ * License: www.highcharts.com/license
20
+ */
21
+ 'use strict';
22
+ /**
23
+ * Mathematical Functionility
24
+ */
25
+ var deg2rad = H.deg2rad,
26
+ pick = H.pick;
27
+ /**
28
+ * Apply 3-D rotation
29
+ * Euler Angles (XYZ): cosA = cos(Alfa|Roll), cosB = cos(Beta|Pitch), cosG = cos(Gamma|Yaw)
30
+ *
31
+ * Composite rotation:
32
+ * | cosB * cosG | cosB * sinG | -sinB |
33
+ * | sinA * sinB * cosG - cosA * sinG | sinA * sinB * sinG + cosA * cosG | sinA * cosB |
34
+ * | cosA * sinB * cosG + sinA * sinG | cosA * sinB * sinG - sinA * cosG | cosA * cosB |
35
+ *
36
+ * Now, Gamma/Yaw is not used (angle=0), so we assume cosG = 1 and sinG = 0, so we get:
37
+ * | cosB | 0 | - sinB |
38
+ * | sinA * sinB | cosA | sinA * cosB |
39
+ * | cosA * sinB | - sinA | cosA * cosB |
40
+ *
41
+ * But in browsers, y is reversed, so we get sinA => -sinA. The general result is:
42
+ * | cosB | 0 | - sinB | | x | | px |
43
+ * | - sinA * sinB | cosA | - sinA * cosB | x | y | = | py |
44
+ * | cosA * sinB | sinA | cosA * cosB | | z | | pz |
45
+ */
46
+ function rotate3D(x, y, z, angles) {
47
+ return {
48
+ x: angles.cosB * x - angles.sinB * z,
49
+ y: -angles.sinA * angles.sinB * x + angles.cosA * y - angles.cosB * angles.sinA * z,
50
+ z: angles.cosA * angles.sinB * x + angles.sinA * y + angles.cosA * angles.cosB * z
51
+ };
52
+ }
53
+
54
+ function perspective3D(coordinate, origin, distance) {
55
+ var projection = ((distance > 0) && (distance < Number.POSITIVE_INFINITY)) ? distance / (coordinate.z + origin.z + distance) : 1;
56
+ return {
57
+ x: coordinate.x * projection,
58
+ y: coordinate.y * projection
59
+ };
60
+ }
61
+
62
+ /**
63
+ * Transforms a given array of points according to the angles in chart.options.
64
+ * Parameters:
65
+ * - points: the array of points
66
+ * - chart: the chart
67
+ * - insidePlotArea: wether to verifiy the points are inside the plotArea
68
+ * Returns:
69
+ * - an array of transformed points
70
+ */
71
+ H.perspective = function(points, chart, insidePlotArea) {
72
+ var options3d = chart.options.chart.options3d,
73
+ inverted = insidePlotArea ? chart.inverted : false,
74
+ origin = {
75
+ x: chart.plotWidth / 2,
76
+ y: chart.plotHeight / 2,
77
+ z: options3d.depth / 2,
78
+ vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
79
+ },
80
+ scale = chart.scale3d || 1,
81
+ beta = deg2rad * options3d.beta * (inverted ? -1 : 1),
82
+ alpha = deg2rad * options3d.alpha * (inverted ? -1 : 1),
83
+ angles = {
84
+ cosA: Math.cos(alpha),
85
+ cosB: Math.cos(-beta),
86
+ sinA: Math.sin(alpha),
87
+ sinB: Math.sin(-beta)
88
+ };
89
+
90
+ if (!insidePlotArea) {
91
+ origin.x += chart.plotLeft;
92
+ origin.y += chart.plotTop;
93
+ }
94
+
95
+ // Transform each point
96
+ return H.map(points, function(point) {
97
+ var rotated = rotate3D(
98
+ (inverted ? point.y : point.x) - origin.x,
99
+ (inverted ? point.x : point.y) - origin.y,
100
+ (point.z || 0) - origin.z,
101
+ angles
102
+ ),
103
+ coordinate = perspective3D(rotated, origin, origin.vd); // Apply perspective
104
+
105
+ // Apply translation
106
+ coordinate.x = coordinate.x * scale + origin.x;
107
+ coordinate.y = coordinate.y * scale + origin.y;
108
+ coordinate.z = rotated.z * scale + origin.z;
109
+
110
+ return {
111
+ x: (inverted ? coordinate.y : coordinate.x),
112
+ y: (inverted ? coordinate.x : coordinate.y),
113
+ z: coordinate.z
114
+ };
115
+ });
116
+ };
117
+
118
+ /**
119
+ * Calculate a distance from camera to points - made for calculating zIndex of scatter points.
120
+ * Parameters:
121
+ * - coordinates: The coordinates of the specific point
122
+ * - chart: the chart
123
+ * Returns:
124
+ * - a distance from camera to point
125
+ */
126
+ H.pointCameraDistance = function(coordinates, chart) {
127
+ var options3d = chart.options.chart.options3d,
128
+ cameraPosition = {
129
+ x: chart.plotWidth / 2,
130
+ y: chart.plotHeight / 2,
131
+ z: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0) + options3d.depth
132
+ },
133
+ distance = Math.sqrt(Math.pow(cameraPosition.x - coordinates.plotX, 2) + Math.pow(cameraPosition.y - coordinates.plotY, 2) + Math.pow(cameraPosition.z - coordinates.plotZ, 2));
134
+ return distance;
135
+ };
136
+
137
+ }(Highcharts));
138
+ (function(H) {
139
+ /**
140
+ * (c) 2010-2016 Torstein Honsi
141
+ *
142
+ * License: www.highcharts.com/license
143
+ */
144
+ 'use strict';
145
+ var cos = Math.cos,
146
+ PI = Math.PI,
147
+ sin = Math.sin;
148
+
149
+
150
+ var animObject = H.animObject,
151
+ charts = H.charts,
152
+ color = H.color,
153
+ defined = H.defined,
154
+ deg2rad = H.deg2rad,
155
+ each = H.each,
156
+ extend = H.extend,
157
+ inArray = H.inArray,
158
+ map = H.map,
159
+ merge = H.merge,
160
+ perspective = H.perspective,
161
+ pick = H.pick,
162
+ SVGElement = H.SVGElement,
163
+ SVGRenderer = H.SVGRenderer,
164
+ wrap = H.wrap;
165
+ /***
166
+ EXTENSION TO THE SVG-RENDERER TO ENABLE 3D SHAPES
167
+ ***/
168
+ ////// HELPER METHODS //////
169
+
170
+ var dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2);
171
+
172
+
173
+ //Shoelace algorithm -- http://en.wikipedia.org/wiki/Shoelace_formula
174
+ function shapeArea(vertexes) {
175
+ var area = 0,
176
+ i,
177
+ j;
178
+ for (i = 0; i < vertexes.length; i++) {
179
+ j = (i + 1) % vertexes.length;
180
+ area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
181
+ }
182
+ return area / 2;
183
+ }
184
+
185
+ function averageZ(vertexes) {
186
+ var z = 0,
187
+ i;
188
+ for (i = 0; i < vertexes.length; i++) {
189
+ z += vertexes[i].z;
190
+ }
191
+ return vertexes.length ? z / vertexes.length : 0;
192
+ }
193
+
194
+ /** Method to construct a curved path
195
+ * Can 'wrap' around more then 180 degrees
196
+ */
197
+ function curveTo(cx, cy, rx, ry, start, end, dx, dy) {
198
+ var result = [],
199
+ arcAngle = end - start;
200
+ if ((end > start) && (end - start > Math.PI / 2 + 0.0001)) {
201
+ result = result.concat(curveTo(cx, cy, rx, ry, start, start + (Math.PI / 2), dx, dy));
202
+ result = result.concat(curveTo(cx, cy, rx, ry, start + (Math.PI / 2), end, dx, dy));
203
+ return result;
204
+ }
205
+ if ((end < start) && (start - end > Math.PI / 2 + 0.0001)) {
206
+ result = result.concat(curveTo(cx, cy, rx, ry, start, start - (Math.PI / 2), dx, dy));
207
+ result = result.concat(curveTo(cx, cy, rx, ry, start - (Math.PI / 2), end, dx, dy));
208
+ return result;
209
+ }
210
+ return [
211
+ 'C',
212
+ cx + (rx * Math.cos(start)) - ((rx * dFactor * arcAngle) * Math.sin(start)) + dx,
213
+ cy + (ry * Math.sin(start)) + ((ry * dFactor * arcAngle) * Math.cos(start)) + dy,
214
+ cx + (rx * Math.cos(end)) + ((rx * dFactor * arcAngle) * Math.sin(end)) + dx,
215
+ cy + (ry * Math.sin(end)) - ((ry * dFactor * arcAngle) * Math.cos(end)) + dy,
216
+
217
+ cx + (rx * Math.cos(end)) + dx,
218
+ cy + (ry * Math.sin(end)) + dy
219
+ ];
220
+ }
221
+
222
+
223
+ /**
224
+ * Override the SVGRenderer initiator to add definitions used by brighter and
225
+ * darker faces of the cuboids.
226
+ */
227
+ wrap(SVGRenderer.prototype, 'init', function(proceed) {
228
+ proceed.apply(this, [].slice.call(arguments, 1));
229
+
230
+ each([{
231
+ name: 'darker',
232
+ slope: 0.6
233
+ }, {
234
+ name: 'brighter',
235
+ slope: 1.4
236
+ }], function(cfg) {
237
+ this.definition({
238
+ tagName: 'filter',
239
+ id: 'highcharts-' + cfg.name,
240
+ children: [{
241
+ tagName: 'feComponentTransfer',
242
+ children: [{
243
+ tagName: 'feFuncR',
244
+ type: 'linear',
245
+ slope: cfg.slope
246
+ }, {
247
+ tagName: 'feFuncG',
248
+ type: 'linear',
249
+ slope: cfg.slope
250
+ }, {
251
+ tagName: 'feFuncB',
252
+ type: 'linear',
253
+ slope: cfg.slope
254
+ }]
255
+ }]
256
+ });
257
+ }, this);
258
+ });
259
+
260
+
261
+ SVGRenderer.prototype.toLinePath = function(points, closed) {
262
+ var result = [];
263
+
264
+ // Put "L x y" for each point
265
+ each(points, function(point) {
266
+ result.push('L', point.x, point.y);
267
+ });
268
+
269
+ if (points.length) {
270
+ // Set the first element to M
271
+ result[0] = 'M';
272
+
273
+ // If it is a closed line, add Z
274
+ if (closed) {
275
+ result.push('Z');
276
+ }
277
+ }
278
+
279
+ return result;
280
+ };
281
+
282
+ ////// CUBOIDS //////
283
+ SVGRenderer.prototype.cuboid = function(shapeArgs) {
284
+
285
+ var result = this.g(),
286
+ paths = this.cuboidPath(shapeArgs);
287
+
288
+
289
+
290
+ // create the 3 sides
291
+ result.front = this.path(paths[0]).attr({
292
+ 'class': 'highcharts-3d-front',
293
+ zIndex: paths[3]
294
+ }).add(result);
295
+ result.top = this.path(paths[1]).attr({
296
+ 'class': 'highcharts-3d-top',
297
+ zIndex: paths[4]
298
+ }).add(result);
299
+ result.side = this.path(paths[2]).attr({
300
+ 'class': 'highcharts-3d-side',
301
+ zIndex: paths[5]
302
+ }).add(result);
303
+
304
+ // apply the fill everywhere, the top a bit brighter, the side a bit darker
305
+ result.fillSetter = function(fill) {
306
+ this.front.attr({
307
+ fill: fill
308
+ });
309
+ this.top.attr({
310
+ fill: color(fill).brighten(0.1).get()
311
+ });
312
+ this.side.attr({
313
+ fill: color(fill).brighten(-0.1).get()
314
+ });
315
+
316
+ this.color = fill;
317
+ return this;
318
+ };
319
+
320
+ // apply opacaity everywhere
321
+ result.opacitySetter = function(opacity) {
322
+ this.front.attr({
323
+ opacity: opacity
324
+ });
325
+ this.top.attr({
326
+ opacity: opacity
327
+ });
328
+ this.side.attr({
329
+ opacity: opacity
330
+ });
331
+ return this;
332
+ };
333
+
334
+ result.attr = function(args) {
335
+ if (args.shapeArgs || defined(args.x)) {
336
+ var shapeArgs = args.shapeArgs || args;
337
+ var paths = this.renderer.cuboidPath(shapeArgs);
338
+ this.front.attr({
339
+ d: paths[0],
340
+ zIndex: paths[3]
341
+ });
342
+ this.top.attr({
343
+ d: paths[1],
344
+ zIndex: paths[4]
345
+ });
346
+ this.side.attr({
347
+ d: paths[2],
348
+ zIndex: paths[5]
349
+ });
350
+ } else {
351
+ return H.SVGElement.prototype.attr.call(this, args); // getter returns value
352
+ }
353
+
354
+ return this;
355
+ };
356
+
357
+ result.animate = function(args, duration, complete) {
358
+ if (defined(args.x) && defined(args.y)) {
359
+ var paths = this.renderer.cuboidPath(args);
360
+ this.front.attr({
361
+ zIndex: paths[3]
362
+ }).animate({
363
+ d: paths[0]
364
+ }, duration, complete);
365
+ this.top.attr({
366
+ zIndex: paths[4]
367
+ }).animate({
368
+ d: paths[1]
369
+ }, duration, complete);
370
+ this.side.attr({
371
+ zIndex: paths[5]
372
+ }).animate({
373
+ d: paths[2]
374
+ }, duration, complete);
375
+ this.attr({
376
+ zIndex: -paths[6] // #4774
377
+ });
378
+ } else if (args.opacity) {
379
+ this.front.animate(args, duration, complete);
380
+ this.top.animate(args, duration, complete);
381
+ this.side.animate(args, duration, complete);
382
+ } else {
383
+ SVGElement.prototype.animate.call(this, args, duration, complete);
384
+ }
385
+ return this;
386
+ };
387
+
388
+ // destroy all children
389
+ result.destroy = function() {
390
+ this.front.destroy();
391
+ this.top.destroy();
392
+ this.side.destroy();
393
+
394
+ return null;
395
+ };
396
+
397
+ // Apply the Z index to the cuboid group
398
+ result.attr({
399
+ zIndex: -paths[6]
400
+ });
401
+
402
+ return result;
403
+ };
404
+
405
+ /**
406
+ * Generates a cuboid
407
+ */
408
+ SVGRenderer.prototype.cuboidPath = function(shapeArgs) {
409
+ var x = shapeArgs.x,
410
+ y = shapeArgs.y,
411
+ z = shapeArgs.z,
412
+ h = shapeArgs.height,
413
+ w = shapeArgs.width,
414
+ d = shapeArgs.depth,
415
+ chart = charts[this.chartIndex];
416
+
417
+ // The 8 corners of the cube
418
+ var pArr = [{
419
+ x: x,
420
+ y: y,
421
+ z: z
422
+ }, {
423
+ x: x + w,
424
+ y: y,
425
+ z: z
426
+ }, {
427
+ x: x + w,
428
+ y: y + h,
429
+ z: z
430
+ }, {
431
+ x: x,
432
+ y: y + h,
433
+ z: z
434
+ }, {
435
+ x: x,
436
+ y: y + h,
437
+ z: z + d
438
+ }, {
439
+ x: x + w,
440
+ y: y + h,
441
+ z: z + d
442
+ }, {
443
+ x: x + w,
444
+ y: y,
445
+ z: z + d
446
+ }, {
447
+ x: x,
448
+ y: y,
449
+ z: z + d
450
+ }];
451
+
452
+ // apply perspective
453
+ pArr = perspective(pArr, chart, shapeArgs.insidePlotArea);
454
+
455
+ // helper method to decide which side is visible
456
+ function mapPath(i) {
457
+ return pArr[i];
458
+ }
459
+ var pickShape = function(path1, path2) {
460
+ var ret = [];
461
+ path1 = map(path1, mapPath);
462
+ path2 = map(path2, mapPath);
463
+ if (shapeArea(path1) < 0) {
464
+ ret = path1;
465
+ } else if (shapeArea(path2) < 0) {
466
+ ret = path2;
467
+ }
468
+ return ret;
469
+ };
470
+
471
+ // front or back
472
+ var front = [3, 2, 1, 0];
473
+ var back = [7, 6, 5, 4];
474
+ var path1 = pickShape(front, back);
475
+
476
+ // top or bottom
477
+ var top = [1, 6, 7, 0];
478
+ var bottom = [4, 5, 2, 3];
479
+ var path2 = pickShape(top, bottom);
480
+
481
+ // side
482
+ var right = [1, 2, 5, 6];
483
+ var left = [0, 7, 4, 3];
484
+ var path3 = pickShape(right, left);
485
+
486
+ return [this.toLinePath(path1, true), this.toLinePath(path2, true), this.toLinePath(path3, true), averageZ(path1), averageZ(path2), averageZ(path3), averageZ(map(bottom, mapPath)) * 9e9]; // #4774
487
+ };
488
+
489
+ ////// SECTORS //////
490
+ H.SVGRenderer.prototype.arc3d = function(attribs) {
491
+
492
+ var wrapper = this.g(),
493
+ renderer = wrapper.renderer,
494
+ customAttribs = ['x', 'y', 'r', 'innerR', 'start', 'end'];
495
+
496
+ /**
497
+ * Get custom attributes. Mutate the original object and return an object with only custom attr.
498
+ */
499
+ function suckOutCustom(params) {
500
+ var hasCA = false,
501
+ ca = {};
502
+ for (var key in params) {
503
+ if (inArray(key, customAttribs) !== -1) {
504
+ ca[key] = params[key];
505
+ delete params[key];
506
+ hasCA = true;
507
+ }
508
+ }
509
+ return hasCA ? ca : false;
510
+ }
511
+
512
+ attribs = merge(attribs);
513
+
514
+ attribs.alpha *= deg2rad;
515
+ attribs.beta *= deg2rad;
516
+
517
+ // Create the different sub sections of the shape
518
+ wrapper.top = renderer.path();
519
+ wrapper.side1 = renderer.path();
520
+ wrapper.side2 = renderer.path();
521
+ wrapper.inn = renderer.path();
522
+ wrapper.out = renderer.path();
523
+
524
+ /**
525
+ * Add all faces
526
+ */
527
+ wrapper.onAdd = function() {
528
+ var parent = wrapper.parentGroup,
529
+ className = wrapper.attr('class');
530
+ wrapper.top.add(wrapper);
531
+
532
+ // These faces are added outside the wrapper group because the z index
533
+ // relates to neighbour elements as well
534
+ each(['out', 'inn', 'side1', 'side2'], function(face) {
535
+ wrapper[face]
536
+ .addClass(className + ' highcharts-3d-side')
537
+ .add(parent);
538
+ });
539
+ };
540
+
541
+ /**
542
+ * Compute the transformed paths and set them to the composite shapes
543
+ */
544
+ wrapper.setPaths = function(attribs) {
545
+
546
+ var paths = wrapper.renderer.arc3dPath(attribs),
547
+ zIndex = paths.zTop * 100;
548
+
549
+ wrapper.attribs = attribs;
550
+
551
+ wrapper.top.attr({
552
+ d: paths.top,
553
+ zIndex: paths.zTop
554
+ });
555
+ wrapper.inn.attr({
556
+ d: paths.inn,
557
+ zIndex: paths.zInn
558
+ });
559
+ wrapper.out.attr({
560
+ d: paths.out,
561
+ zIndex: paths.zOut
562
+ });
563
+ wrapper.side1.attr({
564
+ d: paths.side1,
565
+ zIndex: paths.zSide1
566
+ });
567
+ wrapper.side2.attr({
568
+ d: paths.side2,
569
+ zIndex: paths.zSide2
570
+ });
571
+
572
+
573
+ // show all children
574
+ wrapper.zIndex = zIndex;
575
+ wrapper.attr({
576
+ zIndex: zIndex
577
+ });
578
+
579
+ // Set the radial gradient center the first time
580
+ if (attribs.center) {
581
+ wrapper.top.setRadialReference(attribs.center);
582
+ delete attribs.center;
583
+ }
584
+ };
585
+ wrapper.setPaths(attribs);
586
+
587
+ // Apply the fill to the top and a darker shade to the sides
588
+ wrapper.fillSetter = function(value) {
589
+ var darker = color(value).brighten(-0.1).get();
590
+
591
+ this.fill = value;
592
+
593
+ this.side1.attr({
594
+ fill: darker
595
+ });
596
+ this.side2.attr({
597
+ fill: darker
598
+ });
599
+ this.inn.attr({
600
+ fill: darker
601
+ });
602
+ this.out.attr({
603
+ fill: darker
604
+ });
605
+ this.top.attr({
606
+ fill: value
607
+ });
608
+ return this;
609
+ };
610
+
611
+ // Apply the same value to all. These properties cascade down to the children
612
+ // when set to the composite arc3d.
613
+ each(['opacity', 'translateX', 'translateY', 'visibility'], function(setter) {
614
+ wrapper[setter + 'Setter'] = function(value, key) {
615
+ wrapper[key] = value;
616
+ each(['out', 'inn', 'side1', 'side2', 'top'], function(el) {
617
+ wrapper[el].attr(key, value);
618
+ });
619
+ };
620
+ });
621
+
622
+ /**
623
+ * Override attr to remove shape attributes and use those to set child paths
624
+ */
625
+ wrap(wrapper, 'attr', function(proceed, params) {
626
+ var ca;
627
+ if (typeof params === 'object') {
628
+ ca = suckOutCustom(params);
629
+ if (ca) {
630
+ extend(wrapper.attribs, ca);
631
+ wrapper.setPaths(wrapper.attribs);
632
+ }
633
+ }
634
+ return proceed.apply(this, [].slice.call(arguments, 1));
635
+ });
636
+
637
+ /**
638
+ * Override the animate function by sucking out custom parameters related to the shapes directly,
639
+ * and update the shapes from the animation step.
640
+ */
641
+ wrap(wrapper, 'animate', function(proceed, params, animation, complete) {
642
+ var ca,
643
+ from = this.attribs,
644
+ to,
645
+ anim;
646
+
647
+ // Attribute-line properties connected to 3D. These shouldn't have been in the
648
+ // attribs collection in the first place.
649
+ delete params.center;
650
+ delete params.z;
651
+ delete params.depth;
652
+ delete params.alpha;
653
+ delete params.beta;
654
+
655
+ anim = animObject(pick(animation, this.renderer.globalAnimation));
656
+
657
+ if (anim.duration) {
658
+ params = merge(params); // Don't mutate the original object
659
+ ca = suckOutCustom(params);
660
+ params.dummy = 1; // Params need to have a property in order for the step to run (#5765)
661
+
662
+ if (ca) {
663
+ to = ca;
664
+ anim.step = function(a, fx) {
665
+ function interpolate(key) {
666
+ return from[key] + (pick(to[key], from[key]) - from[key]) * fx.pos;
667
+ }
668
+
669
+ if (fx.prop === 'dummy') {
670
+ fx.elem.setPaths(merge(from, {
671
+ x: interpolate('x'),
672
+ y: interpolate('y'),
673
+ r: interpolate('r'),
674
+ innerR: interpolate('innerR'),
675
+ start: interpolate('start'),
676
+ end: interpolate('end')
677
+ }));
678
+ }
679
+ };
680
+ }
681
+ animation = anim; // Only when duration (#5572)
682
+ }
683
+ return proceed.call(this, params, animation, complete);
684
+ });
685
+
686
+ // destroy all children
687
+ wrapper.destroy = function() {
688
+ this.top.destroy();
689
+ this.out.destroy();
690
+ this.inn.destroy();
691
+ this.side1.destroy();
692
+ this.side2.destroy();
693
+
694
+ SVGElement.prototype.destroy.call(this);
695
+ };
696
+ // hide all children
697
+ wrapper.hide = function() {
698
+ this.top.hide();
699
+ this.out.hide();
700
+ this.inn.hide();
701
+ this.side1.hide();
702
+ this.side2.hide();
703
+ };
704
+ wrapper.show = function() {
705
+ this.top.show();
706
+ this.out.show();
707
+ this.inn.show();
708
+ this.side1.show();
709
+ this.side2.show();
710
+ };
711
+ return wrapper;
712
+ };
713
+
714
+ /**
715
+ * Generate the paths required to draw a 3D arc
716
+ */
717
+ SVGRenderer.prototype.arc3dPath = function(shapeArgs) {
718
+ var cx = shapeArgs.x, // x coordinate of the center
719
+ cy = shapeArgs.y, // y coordinate of the center
720
+ start = shapeArgs.start, // start angle
721
+ end = shapeArgs.end - 0.00001, // end angle
722
+ r = shapeArgs.r, // radius
723
+ ir = shapeArgs.innerR, // inner radius
724
+ d = shapeArgs.depth, // depth
725
+ alpha = shapeArgs.alpha, // alpha rotation of the chart
726
+ beta = shapeArgs.beta; // beta rotation of the chart
727
+
728
+ // Derived Variables
729
+ var cs = Math.cos(start), // cosinus of the start angle
730
+ ss = Math.sin(start), // sinus of the start angle
731
+ ce = Math.cos(end), // cosinus of the end angle
732
+ se = Math.sin(end), // sinus of the end angle
733
+ rx = r * Math.cos(beta), // x-radius
734
+ ry = r * Math.cos(alpha), // y-radius
735
+ irx = ir * Math.cos(beta), // x-radius (inner)
736
+ iry = ir * Math.cos(alpha), // y-radius (inner)
737
+ dx = d * Math.sin(beta), // distance between top and bottom in x
738
+ dy = d * Math.sin(alpha); // distance between top and bottom in y
739
+
740
+ // TOP
741
+ var top = ['M', cx + (rx * cs), cy + (ry * ss)];
742
+ top = top.concat(curveTo(cx, cy, rx, ry, start, end, 0, 0));
743
+ top = top.concat([
744
+ 'L', cx + (irx * ce), cy + (iry * se)
745
+ ]);
746
+ top = top.concat(curveTo(cx, cy, irx, iry, end, start, 0, 0));
747
+ top = top.concat(['Z']);
748
+ // OUTSIDE
749
+ var b = (beta > 0 ? Math.PI / 2 : 0),
750
+ a = (alpha > 0 ? 0 : Math.PI / 2);
751
+
752
+ var start2 = start > -b ? start : (end > -b ? -b : start),
753
+ end2 = end < PI - a ? end : (start < PI - a ? PI - a : end),
754
+ midEnd = 2 * PI - a;
755
+
756
+ // When slice goes over bottom middle, need to add both, left and right outer side.
757
+ // Additionally, when we cross right hand edge, create sharp edge. Outer shape/wall:
758
+ //
759
+ // -------
760
+ // / ^ \
761
+ // 4) / / \ \ 1)
762
+ // / / \ \
763
+ // / / \ \
764
+ // (c)=> ==== ==== <=(d)
765
+ // \ \ / /
766
+ // \ \<=(a)/ /
767
+ // \ \ / / <=(b)
768
+ // 3) \ v / 2)
769
+ // -------
770
+ //
771
+ // (a) - inner side
772
+ // (b) - outer side
773
+ // (c) - left edge (sharp)
774
+ // (d) - right edge (sharp)
775
+ // 1..n - rendering order for startAngle = 0, when set to e.g 90, order changes clockwise (1->2, 2->3, n->1) and counterclockwise for negative startAngle
776
+
777
+ var out = ['M', cx + (rx * cos(start2)), cy + (ry * sin(start2))];
778
+ out = out.concat(curveTo(cx, cy, rx, ry, start2, end2, 0, 0));
779
+
780
+ if (end > midEnd && start < midEnd) { // When shape is wide, it can cross both, (c) and (d) edges, when using startAngle
781
+ // Go to outer side
782
+ out = out.concat([
783
+ 'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy
784
+ ]);
785
+ // Curve to the right edge of the slice (d)
786
+ out = out.concat(curveTo(cx, cy, rx, ry, end2, midEnd, dx, dy));
787
+ // Go to the inner side
788
+ out = out.concat([
789
+ 'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd))
790
+ ]);
791
+ // Curve to the true end of the slice
792
+ out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end, 0, 0));
793
+ // Go to the outer side
794
+ out = out.concat([
795
+ 'L', cx + (rx * cos(end)) + dx, cy + (ry * sin(end)) + dy
796
+ ]);
797
+ // Go back to middle (d)
798
+ out = out.concat(curveTo(cx, cy, rx, ry, end, midEnd, dx, dy));
799
+ out = out.concat([
800
+ 'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd))
801
+ ]);
802
+ // Go back to the left edge
803
+ out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end2, 0, 0));
804
+ } else if (end > PI - a && start < PI - a) { // But shape can cross also only (c) edge:
805
+ // Go to outer side
806
+ out = out.concat([
807
+ 'L', cx + (rx * Math.cos(end2)) + dx, cy + (ry * Math.sin(end2)) + dy
808
+ ]);
809
+ // Curve to the true end of the slice
810
+ out = out.concat(curveTo(cx, cy, rx, ry, end2, end, dx, dy));
811
+ // Go to the inner side
812
+ out = out.concat([
813
+ 'L', cx + (rx * Math.cos(end)), cy + (ry * Math.sin(end))
814
+ ]);
815
+ // Go back to the artifical end2
816
+ out = out.concat(curveTo(cx, cy, rx, ry, end, end2, 0, 0));
817
+ }
818
+
819
+ out = out.concat([
820
+ 'L', cx + (rx * Math.cos(end2)) + dx, cy + (ry * Math.sin(end2)) + dy
821
+ ]);
822
+ out = out.concat(curveTo(cx, cy, rx, ry, end2, start2, dx, dy));
823
+ out = out.concat(['Z']);
824
+
825
+ // INSIDE
826
+ var inn = ['M', cx + (irx * cs), cy + (iry * ss)];
827
+ inn = inn.concat(curveTo(cx, cy, irx, iry, start, end, 0, 0));
828
+ inn = inn.concat([
829
+ 'L', cx + (irx * Math.cos(end)) + dx, cy + (iry * Math.sin(end)) + dy
830
+ ]);
831
+ inn = inn.concat(curveTo(cx, cy, irx, iry, end, start, dx, dy));
832
+ inn = inn.concat(['Z']);
833
+
834
+ // SIDES
835
+ var side1 = [
836
+ 'M', cx + (rx * cs), cy + (ry * ss),
837
+ 'L', cx + (rx * cs) + dx, cy + (ry * ss) + dy,
838
+ 'L', cx + (irx * cs) + dx, cy + (iry * ss) + dy,
839
+ 'L', cx + (irx * cs), cy + (iry * ss),
840
+ 'Z'
841
+ ];
842
+ var side2 = [
843
+ 'M', cx + (rx * ce), cy + (ry * se),
844
+ 'L', cx + (rx * ce) + dx, cy + (ry * se) + dy,
845
+ 'L', cx + (irx * ce) + dx, cy + (iry * se) + dy,
846
+ 'L', cx + (irx * ce), cy + (iry * se),
847
+ 'Z'
848
+ ];
849
+
850
+ // correction for changed position of vanishing point caused by alpha and beta rotations
851
+ var angleCorr = Math.atan2(dy, -dx),
852
+ angleEnd = Math.abs(end + angleCorr),
853
+ angleStart = Math.abs(start + angleCorr),
854
+ angleMid = Math.abs((start + end) / 2 + angleCorr);
855
+
856
+ // set to 0-PI range
857
+ function toZeroPIRange(angle) {
858
+ angle = angle % (2 * Math.PI);
859
+ if (angle > Math.PI) {
860
+ angle = 2 * Math.PI - angle;
861
+ }
862
+ return angle;
863
+ }
864
+ angleEnd = toZeroPIRange(angleEnd);
865
+ angleStart = toZeroPIRange(angleStart);
866
+ angleMid = toZeroPIRange(angleMid);
867
+
868
+ // *1e5 is to compensate pInt in zIndexSetter
869
+ var incPrecision = 1e5,
870
+ a1 = angleMid * incPrecision,
871
+ a2 = angleStart * incPrecision,
872
+ a3 = angleEnd * incPrecision;
873
+
874
+ return {
875
+ top: top,
876
+ zTop: Math.PI * incPrecision + 1, // max angle is PI, so this is allways higher
877
+ out: out,
878
+ zOut: Math.max(a1, a2, a3),
879
+ inn: inn,
880
+ zInn: Math.max(a1, a2, a3),
881
+ side1: side1,
882
+ zSide1: a3 * 0.99, // to keep below zOut and zInn in case of same values
883
+ side2: side2,
884
+ zSide2: a2 * 0.99
885
+ };
886
+ };
887
+
888
+ }(Highcharts));
889
+ (function(H) {
890
+ /**
891
+ * (c) 2010-2016 Torstein Honsi
892
+ *
893
+ * License: www.highcharts.com/license
894
+ */
895
+ 'use strict';
896
+ var Chart = H.Chart,
897
+ each = H.each,
898
+ merge = H.merge,
899
+ perspective = H.perspective,
900
+ pick = H.pick,
901
+ wrap = H.wrap;
902
+
903
+ /***
904
+ EXTENSION FOR 3D CHARTS
905
+ ***/
906
+ // Shorthand to check the is3d flag
907
+ Chart.prototype.is3d = function() {
908
+ return this.options.chart.options3d && this.options.chart.options3d.enabled; // #4280
909
+ };
910
+
911
+ Chart.prototype.propsRequireDirtyBox.push('chart.options3d');
912
+ Chart.prototype.propsRequireUpdateSeries.push('chart.options3d');
913
+
914
+ /**
915
+ * Calculate scale of the 3D view. That is required to
916
+ * fit chart's 3D projection into the actual plotting area. Reported as #4933.
917
+ * @notice This function should ideally take the plot values instead of a chart object,
918
+ * but since the chart object is needed for perspective it is not practical.
919
+ * Possible to make both getScale and perspective more logical and also immutable.
920
+ * @param {Object} chart Chart object
921
+ * @param {Number} chart.plotLeft
922
+ * @param {Number} chart.plotWidth
923
+ * @param {Number} chart.plotTop
924
+ * @param {Number} chart.plotHeight
925
+ * @param {Number} depth The depth of the chart
926
+ * @return {Number} The scale to fit the 3D chart into the plotting area.
927
+ */
928
+ function getScale(chart, depth) {
929
+ var plotLeft = chart.plotLeft,
930
+ plotRight = chart.plotWidth + plotLeft,
931
+ plotTop = chart.plotTop,
932
+ plotBottom = chart.plotHeight + plotTop,
933
+ originX = plotLeft + chart.plotWidth / 2,
934
+ originY = plotTop + chart.plotHeight / 2,
935
+ bbox3d = {
936
+ minX: Number.MAX_VALUE,
937
+ maxX: -Number.MAX_VALUE,
938
+ minY: Number.MAX_VALUE,
939
+ maxY: -Number.MAX_VALUE
940
+ },
941
+ corners,
942
+ scale = 1;
943
+
944
+ // Top left corners:
945
+ corners = [{
946
+ x: plotLeft,
947
+ y: plotTop,
948
+ z: 0
949
+ }, {
950
+ x: plotLeft,
951
+ y: plotTop,
952
+ z: depth
953
+ }];
954
+
955
+ // Top right corners:
956
+ each([0, 1], function(i) {
957
+ corners.push({
958
+ x: plotRight,
959
+ y: corners[i].y,
960
+ z: corners[i].z
961
+ });
962
+ });
963
+
964
+ // All bottom corners:
965
+ each([0, 1, 2, 3], function(i) {
966
+ corners.push({
967
+ x: corners[i].x,
968
+ y: plotBottom,
969
+ z: corners[i].z
970
+ });
971
+ });
972
+
973
+ // Calculate 3D corners:
974
+ corners = perspective(corners, chart, false);
975
+
976
+ // Get bounding box of 3D element:
977
+ each(corners, function(corner) {
978
+ bbox3d.minX = Math.min(bbox3d.minX, corner.x);
979
+ bbox3d.maxX = Math.max(bbox3d.maxX, corner.x);
980
+ bbox3d.minY = Math.min(bbox3d.minY, corner.y);
981
+ bbox3d.maxY = Math.max(bbox3d.maxY, corner.y);
982
+ });
983
+
984
+ // Left edge:
985
+ if (plotLeft > bbox3d.minX) {
986
+ scale = Math.min(scale, 1 - Math.abs((plotLeft + originX) / (bbox3d.minX + originX)) % 1);
987
+ }
988
+
989
+ // Right edge:
990
+ if (plotRight < bbox3d.maxX) {
991
+ scale = Math.min(scale, (plotRight - originX) / (bbox3d.maxX - originX));
992
+ }
993
+
994
+ // Top edge:
995
+ if (plotTop > bbox3d.minY) {
996
+ if (bbox3d.minY < 0) {
997
+ scale = Math.min(scale, (plotTop + originY) / (-bbox3d.minY + plotTop + originY));
998
+ } else {
999
+ scale = Math.min(scale, 1 - (plotTop + originY) / (bbox3d.minY + originY) % 1);
1000
+ }
1001
+ }
1002
+
1003
+ // Bottom edge:
1004
+ if (plotBottom < bbox3d.maxY) {
1005
+ scale = Math.min(scale, Math.abs((plotBottom - originY) / (bbox3d.maxY - originY)));
1006
+ }
1007
+
1008
+ return scale;
1009
+ }
1010
+
1011
+
1012
+
1013
+ H.wrap(H.Chart.prototype, 'isInsidePlot', function(proceed) {
1014
+ return this.is3d() || proceed.apply(this, [].slice.call(arguments, 1));
1015
+ });
1016
+
1017
+ var defaultOptions = H.getOptions();
1018
+ merge(true, defaultOptions, {
1019
+ chart: {
1020
+ options3d: {
1021
+ enabled: false,
1022
+ alpha: 0,
1023
+ beta: 0,
1024
+ depth: 100,
1025
+ fitToPlot: true,
1026
+ viewDistance: 25,
1027
+ frame: {
1028
+ bottom: {
1029
+ size: 1
1030
+ },
1031
+ side: {
1032
+ size: 1
1033
+ },
1034
+ back: {
1035
+ size: 1
1036
+ }
1037
+ }
1038
+ }
1039
+ }
1040
+ });
1041
+
1042
+
1043
+ /**
1044
+ * Override the getContainer by adding the required CSS classes for column
1045
+ * sides (#6018)
1046
+ */
1047
+ wrap(Chart.prototype, 'getContainer', function(proceed) {
1048
+ proceed.apply(this, [].slice.call(arguments, 1));
1049
+
1050
+ this.renderer.definition({
1051
+ tagName: 'style',
1052
+ textContent: '.highcharts-3d-top{' +
1053
+ 'filter: url(#highcharts-brighter)' +
1054
+ '}\n' +
1055
+ '.highcharts-3d-side{' +
1056
+ 'filter: url(#highcharts-darker)' +
1057
+ '}\n'
1058
+ });
1059
+ });
1060
+
1061
+
1062
+ wrap(Chart.prototype, 'setClassName', function(proceed) {
1063
+ proceed.apply(this, [].slice.call(arguments, 1));
1064
+
1065
+ if (this.is3d()) {
1066
+ this.container.className += ' highcharts-3d-chart';
1067
+ }
1068
+ });
1069
+
1070
+ H.wrap(H.Chart.prototype, 'setChartSize', function(proceed) {
1071
+ var chart = this,
1072
+ options3d = chart.options.chart.options3d;
1073
+
1074
+ proceed.apply(chart, [].slice.call(arguments, 1));
1075
+
1076
+ if (chart.is3d()) {
1077
+ var inverted = chart.inverted,
1078
+ clipBox = chart.clipBox,
1079
+ margin = chart.margin,
1080
+ x = inverted ? 'y' : 'x',
1081
+ y = inverted ? 'x' : 'y',
1082
+ w = inverted ? 'height' : 'width',
1083
+ h = inverted ? 'width' : 'height';
1084
+
1085
+ clipBox[x] = -(margin[3] || 0);
1086
+ clipBox[y] = -(margin[0] || 0);
1087
+ clipBox[w] = chart.chartWidth + (margin[3] || 0) + (margin[1] || 0);
1088
+ clipBox[h] = chart.chartHeight + (margin[0] || 0) + (margin[2] || 0);
1089
+
1090
+ // Set scale, used later in perspective method():
1091
+ chart.scale3d = 1; // @notice getScale uses perspective, so scale3d has to be reset.
1092
+ if (options3d.fitToPlot === true) {
1093
+ chart.scale3d = getScale(chart, options3d.depth);
1094
+ }
1095
+ }
1096
+ });
1097
+
1098
+ wrap(Chart.prototype, 'redraw', function(proceed) {
1099
+ if (this.is3d()) {
1100
+ // Set to force a redraw of all elements
1101
+ this.isDirtyBox = true;
1102
+ }
1103
+ proceed.apply(this, [].slice.call(arguments, 1));
1104
+ });
1105
+
1106
+ // Draw the series in the reverse order (#3803, #3917)
1107
+ wrap(Chart.prototype, 'renderSeries', function(proceed) {
1108
+ var series,
1109
+ i = this.series.length;
1110
+
1111
+ if (this.is3d()) {
1112
+ while (i--) {
1113
+ series = this.series[i];
1114
+ series.translate();
1115
+ series.render();
1116
+ }
1117
+ } else {
1118
+ proceed.call(this);
1119
+ }
1120
+ });
1121
+
1122
+ Chart.prototype.retrieveStacks = function(stacking) {
1123
+ var series = this.series,
1124
+ stacks = {},
1125
+ stackNumber,
1126
+ i = 1;
1127
+
1128
+ each(this.series, function(s) {
1129
+ stackNumber = pick(s.options.stack, (stacking ? 0 : series.length - 1 - s.index)); // #3841, #4532
1130
+ if (!stacks[stackNumber]) {
1131
+ stacks[stackNumber] = {
1132
+ series: [s],
1133
+ position: i
1134
+ };
1135
+ i++;
1136
+ } else {
1137
+ stacks[stackNumber].series.push(s);
1138
+ }
1139
+ });
1140
+
1141
+ stacks.totalStacks = i + 1;
1142
+ return stacks;
1143
+ };
1144
+
1145
+ }(Highcharts));
1146
+ (function(H) {
1147
+ /**
1148
+ * (c) 2010-2016 Torstein Honsi
1149
+ *
1150
+ * License: www.highcharts.com/license
1151
+ */
1152
+ 'use strict';
1153
+ var ZAxis,
1154
+
1155
+ Axis = H.Axis,
1156
+ Chart = H.Chart,
1157
+ each = H.each,
1158
+ extend = H.extend,
1159
+ merge = H.merge,
1160
+ perspective = H.perspective,
1161
+ pick = H.pick,
1162
+ splat = H.splat,
1163
+ Tick = H.Tick,
1164
+ wrap = H.wrap;
1165
+ /***
1166
+ EXTENSION TO THE AXIS
1167
+ ***/
1168
+ wrap(Axis.prototype, 'setOptions', function(proceed, userOptions) {
1169
+ var options;
1170
+ proceed.call(this, userOptions);
1171
+ if (this.chart.is3d()) {
1172
+ options = this.options;
1173
+ options.tickWidth = pick(options.tickWidth, 0);
1174
+ options.gridLineWidth = pick(options.gridLineWidth, 1);
1175
+ }
1176
+ });
1177
+
1178
+ wrap(Axis.prototype, 'render', function(proceed) {
1179
+ proceed.apply(this, [].slice.call(arguments, 1));
1180
+
1181
+ // Do not do this if the chart is not 3D
1182
+ if (!this.chart.is3d()) {
1183
+ return;
1184
+ }
1185
+
1186
+ var chart = this.chart,
1187
+ renderer = chart.renderer,
1188
+ options3d = chart.options.chart.options3d,
1189
+ frame = options3d.frame,
1190
+ fbottom = frame.bottom,
1191
+ fback = frame.back,
1192
+ fside = frame.side,
1193
+ depth = options3d.depth,
1194
+ height = this.height,
1195
+ width = this.width,
1196
+ left = this.left,
1197
+ top = this.top;
1198
+
1199
+ if (this.isZAxis) {
1200
+ return;
1201
+ }
1202
+ if (this.horiz) {
1203
+ var bottomShape = {
1204
+ x: left,
1205
+ y: top + (chart.xAxis[0].opposite ? -fbottom.size : height),
1206
+ z: 0,
1207
+ width: width,
1208
+ height: fbottom.size,
1209
+ depth: depth,
1210
+ insidePlotArea: false
1211
+ };
1212
+ if (!this.bottomFrame) {
1213
+ this.bottomFrame = renderer.cuboid(bottomShape).attr({
1214
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
1215
+ 'zIndex': (chart.yAxis[0].reversed && options3d.alpha > 0 ? 4 : -1)
1216
+ }).add();
1217
+
1218
+
1219
+ } else {
1220
+ this.bottomFrame.animate(bottomShape);
1221
+ }
1222
+ } else {
1223
+ // BACK
1224
+ var backShape = {
1225
+ x: left + (chart.yAxis[0].opposite ? 0 : -fside.size),
1226
+ y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
1227
+ z: depth,
1228
+ width: width + fside.size,
1229
+ height: height + fbottom.size,
1230
+ depth: fback.size,
1231
+ insidePlotArea: false
1232
+ };
1233
+ if (!this.backFrame) {
1234
+ this.backFrame = renderer.cuboid(backShape).attr({
1235
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-back',
1236
+ zIndex: -3
1237
+ }).add();
1238
+
1239
+
1240
+ } else {
1241
+ this.backFrame.animate(backShape);
1242
+ }
1243
+ var sideShape = {
1244
+ x: left + (chart.yAxis[0].opposite ? width : -fside.size),
1245
+ y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
1246
+ z: 0,
1247
+ width: fside.size,
1248
+ height: height + fbottom.size,
1249
+ depth: depth,
1250
+ insidePlotArea: false
1251
+ };
1252
+ if (!this.sideFrame) {
1253
+ this.sideFrame = renderer.cuboid(sideShape).attr({
1254
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-side',
1255
+ zIndex: -2
1256
+ }).add();
1257
+
1258
+
1259
+
1260
+ } else {
1261
+ this.sideFrame.animate(sideShape);
1262
+ }
1263
+ }
1264
+ });
1265
+
1266
+ wrap(Axis.prototype, 'getPlotLinePath', function(proceed) {
1267
+ var path = proceed.apply(this, [].slice.call(arguments, 1));
1268
+
1269
+ // Do not do this if the chart is not 3D
1270
+ if (!this.chart.is3d()) {
1271
+ return path;
1272
+ }
1273
+
1274
+ if (path === null) {
1275
+ return path;
1276
+ }
1277
+
1278
+ var chart = this.chart,
1279
+ options3d = chart.options.chart.options3d,
1280
+ d = this.isZAxis ? chart.plotWidth : options3d.depth,
1281
+ opposite = this.opposite;
1282
+ if (this.horiz) {
1283
+ opposite = !opposite;
1284
+ }
1285
+ var pArr = [
1286
+ this.swapZ({
1287
+ x: path[1],
1288
+ y: path[2],
1289
+ z: (opposite ? d : 0)
1290
+ }),
1291
+ this.swapZ({
1292
+ x: path[1],
1293
+ y: path[2],
1294
+ z: d
1295
+ }),
1296
+ this.swapZ({
1297
+ x: path[4],
1298
+ y: path[5],
1299
+ z: d
1300
+ }),
1301
+ this.swapZ({
1302
+ x: path[4],
1303
+ y: path[5],
1304
+ z: (opposite ? 0 : d)
1305
+ })
1306
+ ];
1307
+
1308
+ pArr = perspective(pArr, this.chart, false);
1309
+ path = this.chart.renderer.toLinePath(pArr, false);
1310
+
1311
+ return path;
1312
+ });
1313
+
1314
+ // Do not draw axislines in 3D
1315
+ wrap(Axis.prototype, 'getLinePath', function(proceed) {
1316
+ return this.chart.is3d() ? [] : proceed.apply(this, [].slice.call(arguments, 1));
1317
+ });
1318
+
1319
+ wrap(Axis.prototype, 'getPlotBandPath', function(proceed) {
1320
+ // Do not do this if the chart is not 3D
1321
+ if (!this.chart.is3d()) {
1322
+ return proceed.apply(this, [].slice.call(arguments, 1));
1323
+ }
1324
+
1325
+ var args = arguments,
1326
+ from = args[1],
1327
+ to = args[2],
1328
+ toPath = this.getPlotLinePath(to),
1329
+ path = this.getPlotLinePath(from);
1330
+
1331
+ if (path && toPath) {
1332
+ path.push(
1333
+ 'L',
1334
+ toPath[10], // These two do not exist in the regular getPlotLine
1335
+ toPath[11], // ---- # 3005
1336
+ 'L',
1337
+ toPath[7],
1338
+ toPath[8],
1339
+ 'L',
1340
+ toPath[4],
1341
+ toPath[5],
1342
+ 'L',
1343
+ toPath[1],
1344
+ toPath[2]
1345
+ );
1346
+ } else { // outside the axis area
1347
+ path = null;
1348
+ }
1349
+
1350
+ return path;
1351
+ });
1352
+
1353
+ /***
1354
+ EXTENSION TO THE TICKS
1355
+ ***/
1356
+
1357
+ wrap(Tick.prototype, 'getMarkPath', function(proceed) {
1358
+ var path = proceed.apply(this, [].slice.call(arguments, 1));
1359
+
1360
+ // Do not do this if the chart is not 3D
1361
+ if (!this.axis.chart.is3d()) {
1362
+ return path;
1363
+ }
1364
+
1365
+ var pArr = [
1366
+ this.axis.swapZ({
1367
+ x: path[1],
1368
+ y: path[2],
1369
+ z: 0
1370
+ }),
1371
+ this.axis.swapZ({
1372
+ x: path[4],
1373
+ y: path[5],
1374
+ z: 0
1375
+ })
1376
+ ];
1377
+
1378
+ pArr = perspective(pArr, this.axis.chart, false);
1379
+ path = [
1380
+ 'M', pArr[0].x, pArr[0].y,
1381
+ 'L', pArr[1].x, pArr[1].y
1382
+ ];
1383
+ return path;
1384
+ });
1385
+
1386
+ wrap(Tick.prototype, 'getLabelPosition', function(proceed) {
1387
+ var pos = proceed.apply(this, [].slice.call(arguments, 1));
1388
+
1389
+ // Do not do this if the chart is not 3D
1390
+ if (this.axis.chart.is3d()) {
1391
+ pos = perspective([this.axis.swapZ({
1392
+ x: pos.x,
1393
+ y: pos.y,
1394
+ z: 0
1395
+ })], this.axis.chart, false)[0];
1396
+ }
1397
+ return pos;
1398
+ });
1399
+
1400
+ H.wrap(Axis.prototype, 'getTitlePosition', function(proceed) {
1401
+ var is3d = this.chart.is3d(),
1402
+ pos,
1403
+ axisTitleMargin;
1404
+
1405
+ // Pull out the axis title margin, that is not subject to the perspective
1406
+ if (is3d) {
1407
+ axisTitleMargin = this.axisTitleMargin;
1408
+ this.axisTitleMargin = 0;
1409
+ }
1410
+
1411
+ pos = proceed.apply(this, [].slice.call(arguments, 1));
1412
+
1413
+ if (is3d) {
1414
+ pos = perspective([this.swapZ({
1415
+ x: pos.x,
1416
+ y: pos.y,
1417
+ z: 0
1418
+ })], this.chart, false)[0];
1419
+
1420
+ // Re-apply the axis title margin outside the perspective
1421
+ pos[this.horiz ? 'y' : 'x'] += (this.horiz ? 1 : -1) * // horizontal axis reverses the margin ...
1422
+ (this.opposite ? -1 : 1) * // ... so does opposite axes
1423
+ axisTitleMargin;
1424
+ this.axisTitleMargin = axisTitleMargin;
1425
+ }
1426
+ return pos;
1427
+ });
1428
+
1429
+ wrap(Axis.prototype, 'drawCrosshair', function(proceed) {
1430
+ var args = arguments;
1431
+ if (this.chart.is3d()) {
1432
+ if (args[2]) {
1433
+ args[2] = {
1434
+ plotX: args[2].plotXold || args[2].plotX,
1435
+ plotY: args[2].plotYold || args[2].plotY
1436
+ };
1437
+ }
1438
+ }
1439
+ proceed.apply(this, [].slice.call(args, 1));
1440
+ });
1441
+
1442
+ /***
1443
+ Z-AXIS
1444
+ ***/
1445
+
1446
+ Axis.prototype.swapZ = function(p, insidePlotArea) {
1447
+ if (this.isZAxis) {
1448
+ var plotLeft = insidePlotArea ? 0 : this.chart.plotLeft;
1449
+ var chart = this.chart;
1450
+ return {
1451
+ x: plotLeft + (chart.yAxis[0].opposite ? p.z : chart.xAxis[0].width - p.z),
1452
+ y: p.y,
1453
+ z: p.x - plotLeft
1454
+ };
1455
+ }
1456
+ return p;
1457
+ };
1458
+
1459
+ ZAxis = H.ZAxis = function() {
1460
+ this.isZAxis = true;
1461
+ this.init.apply(this, arguments);
1462
+ };
1463
+ extend(ZAxis.prototype, Axis.prototype);
1464
+ extend(ZAxis.prototype, {
1465
+ setOptions: function(userOptions) {
1466
+ userOptions = merge({
1467
+ offset: 0,
1468
+ lineWidth: 0
1469
+ }, userOptions);
1470
+ Axis.prototype.setOptions.call(this, userOptions);
1471
+ this.coll = 'zAxis';
1472
+ },
1473
+ setAxisSize: function() {
1474
+ Axis.prototype.setAxisSize.call(this);
1475
+ this.width = this.len = this.chart.options.chart.options3d.depth;
1476
+ this.right = this.chart.chartWidth - this.width - this.left;
1477
+ },
1478
+ getSeriesExtremes: function() {
1479
+ var axis = this,
1480
+ chart = axis.chart;
1481
+
1482
+ axis.hasVisibleSeries = false;
1483
+
1484
+ // Reset properties in case we're redrawing (#3353)
1485
+ axis.dataMin = axis.dataMax = axis.ignoreMinPadding = axis.ignoreMaxPadding = null;
1486
+
1487
+ if (axis.buildStacks) {
1488
+ axis.buildStacks();
1489
+ }
1490
+
1491
+ // loop through this axis' series
1492
+ each(axis.series, function(series) {
1493
+
1494
+ if (series.visible || !chart.options.chart.ignoreHiddenSeries) {
1495
+
1496
+ var seriesOptions = series.options,
1497
+ zData,
1498
+ threshold = seriesOptions.threshold;
1499
+
1500
+ axis.hasVisibleSeries = true;
1501
+
1502
+ // Validate threshold in logarithmic axes
1503
+ if (axis.isLog && threshold <= 0) {
1504
+ threshold = null;
1505
+ }
1506
+
1507
+ zData = series.zData;
1508
+ if (zData.length) {
1509
+ axis.dataMin = Math.min(pick(axis.dataMin, zData[0]), Math.min.apply(null, zData));
1510
+ axis.dataMax = Math.max(pick(axis.dataMax, zData[0]), Math.max.apply(null, zData));
1511
+ }
1512
+ }
1513
+ });
1514
+ }
1515
+ });
1516
+
1517
+
1518
+ /**
1519
+ * Extend the chart getAxes method to also get the color axis
1520
+ */
1521
+ wrap(Chart.prototype, 'getAxes', function(proceed) {
1522
+ var chart = this,
1523
+ options = this.options,
1524
+ zAxisOptions = options.zAxis = splat(options.zAxis || {});
1525
+
1526
+ proceed.call(this);
1527
+
1528
+ if (!chart.is3d()) {
1529
+ return;
1530
+ }
1531
+ this.zAxis = [];
1532
+ each(zAxisOptions, function(axisOptions, i) {
1533
+ axisOptions.index = i;
1534
+ axisOptions.isX = true; //Z-Axis is shown horizontally, so it's kind of a X-Axis
1535
+ var zAxis = new ZAxis(chart, axisOptions);
1536
+ zAxis.setScale();
1537
+ });
1538
+ });
1539
+
1540
+ }(Highcharts));
1541
+ (function(H) {
1542
+ /**
1543
+ * (c) 2010-2016 Torstein Honsi
1544
+ *
1545
+ * License: www.highcharts.com/license
1546
+ */
1547
+ 'use strict';
1548
+ var each = H.each,
1549
+ perspective = H.perspective,
1550
+ pick = H.pick,
1551
+ Series = H.Series,
1552
+ seriesTypes = H.seriesTypes,
1553
+ svg = H.svg,
1554
+ wrap = H.wrap;
1555
+ /***
1556
+ EXTENSION FOR 3D COLUMNS
1557
+ ***/
1558
+ wrap(seriesTypes.column.prototype, 'translate', function(proceed) {
1559
+ proceed.apply(this, [].slice.call(arguments, 1));
1560
+
1561
+ // Do not do this if the chart is not 3D
1562
+ if (!this.chart.is3d()) {
1563
+ return;
1564
+ }
1565
+
1566
+ var series = this,
1567
+ chart = series.chart,
1568
+ seriesOptions = series.options,
1569
+ depth = seriesOptions.depth || 25;
1570
+
1571
+ var stack = seriesOptions.stacking ? (seriesOptions.stack || 0) : series._i;
1572
+ var z = stack * (depth + (seriesOptions.groupZPadding || 1));
1573
+
1574
+ if (seriesOptions.grouping !== false) {
1575
+ z = 0;
1576
+ }
1577
+
1578
+ z += (seriesOptions.groupZPadding || 1);
1579
+
1580
+ each(series.data, function(point) {
1581
+ if (point.y !== null) {
1582
+ var shapeArgs = point.shapeArgs,
1583
+ tooltipPos = point.tooltipPos;
1584
+
1585
+ point.shapeType = 'cuboid';
1586
+ shapeArgs.z = z;
1587
+ shapeArgs.depth = depth;
1588
+ shapeArgs.insidePlotArea = true;
1589
+
1590
+ // Translate the tooltip position in 3d space
1591
+ tooltipPos = perspective([{
1592
+ x: tooltipPos[0],
1593
+ y: tooltipPos[1],
1594
+ z: z
1595
+ }], chart, true)[0];
1596
+ point.tooltipPos = [tooltipPos.x, tooltipPos.y];
1597
+ }
1598
+ });
1599
+ // store for later use #4067
1600
+ series.z = z;
1601
+ });
1602
+
1603
+ wrap(seriesTypes.column.prototype, 'animate', function(proceed) {
1604
+ if (!this.chart.is3d()) {
1605
+ proceed.apply(this, [].slice.call(arguments, 1));
1606
+ } else {
1607
+ var args = arguments,
1608
+ init = args[1],
1609
+ yAxis = this.yAxis,
1610
+ series = this,
1611
+ reversed = this.yAxis.reversed;
1612
+
1613
+ if (svg) { // VML is too slow anyway
1614
+ if (init) {
1615
+ each(series.data, function(point) {
1616
+ if (point.y !== null) {
1617
+ point.height = point.shapeArgs.height;
1618
+ point.shapey = point.shapeArgs.y; //#2968
1619
+ point.shapeArgs.height = 1;
1620
+ if (!reversed) {
1621
+ if (point.stackY) {
1622
+ point.shapeArgs.y = point.plotY + yAxis.translate(point.stackY);
1623
+ } else {
1624
+ point.shapeArgs.y = point.plotY + (point.negative ? -point.height : point.height);
1625
+ }
1626
+ }
1627
+ }
1628
+ });
1629
+
1630
+ } else { // run the animation
1631
+ each(series.data, function(point) {
1632
+ if (point.y !== null) {
1633
+ point.shapeArgs.height = point.height;
1634
+ point.shapeArgs.y = point.shapey; //#2968
1635
+ // null value do not have a graphic
1636
+ if (point.graphic) {
1637
+ point.graphic.animate(point.shapeArgs, series.options.animation);
1638
+ }
1639
+ }
1640
+ });
1641
+
1642
+ // redraw datalabels to the correct position
1643
+ this.drawDataLabels();
1644
+
1645
+ // delete this function to allow it only once
1646
+ series.animate = null;
1647
+ }
1648
+ }
1649
+ }
1650
+ });
1651
+
1652
+ wrap(seriesTypes.column.prototype, 'init', function(proceed) {
1653
+ proceed.apply(this, [].slice.call(arguments, 1));
1654
+
1655
+ if (this.chart.is3d()) {
1656
+ var seriesOptions = this.options,
1657
+ grouping = seriesOptions.grouping,
1658
+ stacking = seriesOptions.stacking,
1659
+ reversedStacks = pick(this.yAxis.options.reversedStacks, true),
1660
+ z = 0;
1661
+
1662
+ if (!(grouping !== undefined && !grouping)) {
1663
+ var stacks = this.chart.retrieveStacks(stacking),
1664
+ stack = seriesOptions.stack || 0,
1665
+ i; // position within the stack
1666
+ for (i = 0; i < stacks[stack].series.length; i++) {
1667
+ if (stacks[stack].series[i] === this) {
1668
+ break;
1669
+ }
1670
+ }
1671
+ z = (10 * (stacks.totalStacks - stacks[stack].position)) + (reversedStacks ? i : -i); // #4369
1672
+
1673
+ // In case when axis is reversed, columns are also reversed inside the group (#3737)
1674
+ if (!this.xAxis.reversed) {
1675
+ z = (stacks.totalStacks * 10) - z;
1676
+ }
1677
+ }
1678
+
1679
+ seriesOptions.zIndex = z;
1680
+ }
1681
+ });
1682
+
1683
+
1684
+
1685
+ function draw3DPoints(proceed) {
1686
+ // Do not do this if the chart is not 3D
1687
+ if (this.chart.is3d()) {
1688
+ var grouping = this.chart.options.plotOptions.column.grouping;
1689
+ if (grouping !== undefined && !grouping && this.group.zIndex !== undefined && !this.zIndexSet) {
1690
+ this.group.attr({
1691
+ zIndex: this.group.zIndex * 10
1692
+ });
1693
+ this.zIndexSet = true; // #4062 set zindex only once
1694
+ }
1695
+ }
1696
+
1697
+ proceed.apply(this, [].slice.call(arguments, 1));
1698
+ }
1699
+
1700
+ wrap(Series.prototype, 'alignDataLabel', function(proceed) {
1701
+
1702
+ // Only do this for 3D columns and columnranges
1703
+ if (this.chart.is3d() && (this.type === 'column' || this.type === 'columnrange')) {
1704
+ var series = this,
1705
+ chart = series.chart;
1706
+
1707
+ var args = arguments,
1708
+ alignTo = args[4];
1709
+
1710
+ var pos = ({
1711
+ x: alignTo.x,
1712
+ y: alignTo.y,
1713
+ z: series.z
1714
+ });
1715
+ pos = perspective([pos], chart, true)[0];
1716
+ alignTo.x = pos.x;
1717
+ alignTo.y = pos.y;
1718
+ }
1719
+
1720
+ proceed.apply(this, [].slice.call(arguments, 1));
1721
+ });
1722
+
1723
+ if (seriesTypes.columnrange) {
1724
+ wrap(seriesTypes.columnrange.prototype, 'drawPoints', draw3DPoints);
1725
+ }
1726
+
1727
+ wrap(seriesTypes.column.prototype, 'drawPoints', draw3DPoints);
1728
+
1729
+ /***
1730
+ EXTENSION FOR 3D CYLINDRICAL COLUMNS
1731
+ Not supported
1732
+ ***/
1733
+ /*
1734
+ var defaultOptions = H.getOptions();
1735
+ defaultOptions.plotOptions.cylinder = H.merge(defaultOptions.plotOptions.column);
1736
+ var CylinderSeries = H.extendClass(seriesTypes.column, {
1737
+ type: 'cylinder'
1738
+ });
1739
+ seriesTypes.cylinder = CylinderSeries;
1740
+
1741
+ wrap(seriesTypes.cylinder.prototype, 'translate', function (proceed) {
1742
+ proceed.apply(this, [].slice.call(arguments, 1));
1743
+
1744
+ // Do not do this if the chart is not 3D
1745
+ if (!this.chart.is3d()) {
1746
+ return;
1747
+ }
1748
+
1749
+ var series = this,
1750
+ chart = series.chart,
1751
+ options = chart.options,
1752
+ cylOptions = options.plotOptions.cylinder,
1753
+ options3d = options.chart.options3d,
1754
+ depth = cylOptions.depth || 0,
1755
+ alpha = chart.alpha3d;
1756
+
1757
+ var z = cylOptions.stacking ? (this.options.stack || 0) * depth : series._i * depth;
1758
+ z += depth / 2;
1759
+
1760
+ if (cylOptions.grouping !== false) { z = 0; }
1761
+
1762
+ each(series.data, function (point) {
1763
+ var shapeArgs = point.shapeArgs,
1764
+ deg2rad = H.deg2rad;
1765
+ point.shapeType = 'arc3d';
1766
+ shapeArgs.x += depth / 2;
1767
+ shapeArgs.z = z;
1768
+ shapeArgs.start = 0;
1769
+ shapeArgs.end = 2 * PI;
1770
+ shapeArgs.r = depth * 0.95;
1771
+ shapeArgs.innerR = 0;
1772
+ shapeArgs.depth = shapeArgs.height * (1 / sin((90 - alpha) * deg2rad)) - z;
1773
+ shapeArgs.alpha = 90 - alpha;
1774
+ shapeArgs.beta = 0;
1775
+ });
1776
+ });
1777
+ */
1778
+
1779
+ }(Highcharts));
1780
+ (function(H) {
1781
+ /**
1782
+ * (c) 2010-2016 Torstein Honsi
1783
+ *
1784
+ * License: www.highcharts.com/license
1785
+ */
1786
+ 'use strict';
1787
+ var deg2rad = H.deg2rad,
1788
+ each = H.each,
1789
+ pick = H.pick,
1790
+ seriesTypes = H.seriesTypes,
1791
+ svg = H.svg,
1792
+ wrap = H.wrap;
1793
+
1794
+ /***
1795
+ EXTENSION FOR 3D PIES
1796
+ ***/
1797
+
1798
+ wrap(seriesTypes.pie.prototype, 'translate', function(proceed) {
1799
+ proceed.apply(this, [].slice.call(arguments, 1));
1800
+
1801
+ // Do not do this if the chart is not 3D
1802
+ if (!this.chart.is3d()) {
1803
+ return;
1804
+ }
1805
+
1806
+ var series = this,
1807
+ seriesOptions = series.options,
1808
+ depth = seriesOptions.depth || 0,
1809
+ options3d = series.chart.options.chart.options3d,
1810
+ alpha = options3d.alpha,
1811
+ beta = options3d.beta,
1812
+ z = seriesOptions.stacking ? (seriesOptions.stack || 0) * depth : series._i * depth;
1813
+
1814
+ z += depth / 2;
1815
+
1816
+ if (seriesOptions.grouping !== false) {
1817
+ z = 0;
1818
+ }
1819
+
1820
+ each(series.data, function(point) {
1821
+
1822
+ var shapeArgs = point.shapeArgs,
1823
+ angle;
1824
+
1825
+ point.shapeType = 'arc3d';
1826
+
1827
+ shapeArgs.z = z;
1828
+ shapeArgs.depth = depth * 0.75;
1829
+ shapeArgs.alpha = alpha;
1830
+ shapeArgs.beta = beta;
1831
+ shapeArgs.center = series.center;
1832
+
1833
+ angle = (shapeArgs.end + shapeArgs.start) / 2;
1834
+
1835
+ point.slicedTranslation = {
1836
+ translateX: Math.round(Math.cos(angle) * seriesOptions.slicedOffset * Math.cos(alpha * deg2rad)),
1837
+ translateY: Math.round(Math.sin(angle) * seriesOptions.slicedOffset * Math.cos(alpha * deg2rad))
1838
+ };
1839
+ });
1840
+ });
1841
+
1842
+ wrap(seriesTypes.pie.prototype.pointClass.prototype, 'haloPath', function(proceed) {
1843
+ var args = arguments;
1844
+ return this.series.chart.is3d() ? [] : proceed.call(this, args[1]);
1845
+ });
1846
+
1847
+
1848
+
1849
+ wrap(seriesTypes.pie.prototype, 'drawPoints', function(proceed) {
1850
+ proceed.apply(this, [].slice.call(arguments, 1));
1851
+
1852
+ if (this.chart.is3d()) {
1853
+ each(this.points, function(point) {
1854
+ var graphic = point.graphic;
1855
+
1856
+ // #4584 Check if has graphic - null points don't have it
1857
+ if (graphic) {
1858
+ // Hide null or 0 points (#3006, 3650)
1859
+ graphic[point.y && point.visible ? 'show' : 'hide']();
1860
+ }
1861
+ });
1862
+ }
1863
+ });
1864
+
1865
+ wrap(seriesTypes.pie.prototype, 'drawDataLabels', function(proceed) {
1866
+ if (this.chart.is3d()) {
1867
+ var series = this,
1868
+ chart = series.chart,
1869
+ options3d = chart.options.chart.options3d;
1870
+ each(series.data, function(point) {
1871
+ var shapeArgs = point.shapeArgs,
1872
+ r = shapeArgs.r,
1873
+ a1 = (shapeArgs.alpha || options3d.alpha) * deg2rad, //#3240 issue with datalabels for 0 and null values
1874
+ b1 = (shapeArgs.beta || options3d.beta) * deg2rad,
1875
+ a2 = (shapeArgs.start + shapeArgs.end) / 2,
1876
+ labelPos = point.labelPos,
1877
+ labelIndexes = [0, 2, 4], // [x1, y1, x2, y2, x3, y3]
1878
+ yOffset = (-r * (1 - Math.cos(a1)) * Math.sin(a2)), // + (sin(a2) > 0 ? sin(a1) * d : 0)
1879
+ xOffset = r * (Math.cos(b1) - 1) * Math.cos(a2);
1880
+
1881
+ // Apply perspective on label positions
1882
+ each(labelIndexes, function(index) {
1883
+ labelPos[index] += xOffset;
1884
+ labelPos[index + 1] += yOffset;
1885
+ });
1886
+ });
1887
+ }
1888
+
1889
+ proceed.apply(this, [].slice.call(arguments, 1));
1890
+ });
1891
+
1892
+ wrap(seriesTypes.pie.prototype, 'addPoint', function(proceed) {
1893
+ proceed.apply(this, [].slice.call(arguments, 1));
1894
+ if (this.chart.is3d()) {
1895
+ // destroy (and rebuild) everything!!!
1896
+ this.update(this.userOptions, true); // #3845 pass the old options
1897
+ }
1898
+ });
1899
+
1900
+ wrap(seriesTypes.pie.prototype, 'animate', function(proceed) {
1901
+ if (!this.chart.is3d()) {
1902
+ proceed.apply(this, [].slice.call(arguments, 1));
1903
+ } else {
1904
+ var args = arguments,
1905
+ init = args[1],
1906
+ animation = this.options.animation,
1907
+ attribs,
1908
+ center = this.center,
1909
+ group = this.group,
1910
+ markerGroup = this.markerGroup;
1911
+
1912
+ if (svg) { // VML is too slow anyway
1913
+
1914
+ if (animation === true) {
1915
+ animation = {};
1916
+ }
1917
+ // Initialize the animation
1918
+ if (init) {
1919
+
1920
+ // Scale down the group and place it in the center
1921
+ group.oldtranslateX = group.translateX;
1922
+ group.oldtranslateY = group.translateY;
1923
+ attribs = {
1924
+ translateX: center[0],
1925
+ translateY: center[1],
1926
+ scaleX: 0.001, // #1499
1927
+ scaleY: 0.001
1928
+ };
1929
+
1930
+ group.attr(attribs);
1931
+ if (markerGroup) {
1932
+ markerGroup.attrSetters = group.attrSetters;
1933
+ markerGroup.attr(attribs);
1934
+ }
1935
+
1936
+ // Run the animation
1937
+ } else {
1938
+ attribs = {
1939
+ translateX: group.oldtranslateX,
1940
+ translateY: group.oldtranslateY,
1941
+ scaleX: 1,
1942
+ scaleY: 1
1943
+ };
1944
+ group.animate(attribs, animation);
1945
+
1946
+ if (markerGroup) {
1947
+ markerGroup.animate(attribs, animation);
1948
+ }
1949
+
1950
+ // Delete this function to allow it only once
1951
+ this.animate = null;
1952
+ }
1953
+
1954
+ }
1955
+ }
1956
+ });
1957
+
1958
+ }(Highcharts));
1959
+ (function(H) {
1960
+ /**
1961
+ * (c) 2010-2016 Torstein Honsi
1962
+ *
1963
+ * License: www.highcharts.com/license
1964
+ */
1965
+ 'use strict';
1966
+ var perspective = H.perspective,
1967
+ pick = H.pick,
1968
+ Point = H.Point,
1969
+ seriesTypes = H.seriesTypes,
1970
+ wrap = H.wrap;
1971
+
1972
+ /***
1973
+ EXTENSION FOR 3D SCATTER CHART
1974
+ ***/
1975
+
1976
+ wrap(seriesTypes.scatter.prototype, 'translate', function(proceed) {
1977
+ //function translate3d(proceed) {
1978
+ proceed.apply(this, [].slice.call(arguments, 1));
1979
+
1980
+ if (!this.chart.is3d()) {
1981
+ return;
1982
+ }
1983
+
1984
+ var series = this,
1985
+ chart = series.chart,
1986
+ zAxis = pick(series.zAxis, chart.options.zAxis[0]),
1987
+ rawPoints = [],
1988
+ rawPoint,
1989
+ projectedPoints,
1990
+ projectedPoint,
1991
+ zValue,
1992
+ i;
1993
+
1994
+ for (i = 0; i < series.data.length; i++) {
1995
+ rawPoint = series.data[i];
1996
+ zValue = zAxis.isLog && zAxis.val2lin ? zAxis.val2lin(rawPoint.z) : rawPoint.z; // #4562
1997
+ rawPoint.plotZ = zAxis.translate(zValue);
1998
+
1999
+ rawPoint.isInside = rawPoint.isInside ? (zValue >= zAxis.min && zValue <= zAxis.max) : false;
2000
+
2001
+ rawPoints.push({
2002
+ x: rawPoint.plotX,
2003
+ y: rawPoint.plotY,
2004
+ z: rawPoint.plotZ
2005
+ });
2006
+ }
2007
+
2008
+ projectedPoints = perspective(rawPoints, chart, true);
2009
+
2010
+ for (i = 0; i < series.data.length; i++) {
2011
+ rawPoint = series.data[i];
2012
+ projectedPoint = projectedPoints[i];
2013
+
2014
+ rawPoint.plotXold = rawPoint.plotX;
2015
+ rawPoint.plotYold = rawPoint.plotY;
2016
+ rawPoint.plotZold = rawPoint.plotZ;
2017
+
2018
+ rawPoint.plotX = projectedPoint.x;
2019
+ rawPoint.plotY = projectedPoint.y;
2020
+ rawPoint.plotZ = projectedPoint.z;
2021
+
2022
+ }
2023
+
2024
+ });
2025
+
2026
+
2027
+ wrap(seriesTypes.scatter.prototype, 'init', function(proceed, chart, options) {
2028
+ if (chart.is3d()) {
2029
+ // add a third coordinate
2030
+ this.axisTypes = ['xAxis', 'yAxis', 'zAxis'];
2031
+ this.pointArrayMap = ['x', 'y', 'z'];
2032
+ this.parallelArrays = ['x', 'y', 'z'];
2033
+
2034
+ // Require direct touch rather than using the k-d-tree, because the k-d-tree currently doesn't
2035
+ // take the xyz coordinate system into account (#4552)
2036
+ this.directTouch = true;
2037
+ }
2038
+
2039
+ var result = proceed.apply(this, [chart, options]);
2040
+
2041
+ if (this.chart.is3d()) {
2042
+ // Set a new default tooltip formatter
2043
+ var default3dScatterTooltip = 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>z: <b>{point.z}</b><br/>';
2044
+ if (this.userOptions.tooltip) {
2045
+ this.tooltipOptions.pointFormat = this.userOptions.tooltip.pointFormat || default3dScatterTooltip;
2046
+ } else {
2047
+ this.tooltipOptions.pointFormat = default3dScatterTooltip;
2048
+ }
2049
+ }
2050
+ return result;
2051
+ });
2052
+
2053
+ /**
2054
+ * Updating zIndex for every point - based on the distance from point to camera
2055
+ */
2056
+ wrap(seriesTypes.scatter.prototype, 'pointAttribs', function(proceed, point) {
2057
+ var pointOptions = proceed.apply(this, [].slice.call(arguments, 1));
2058
+ if (this.chart.is3d() && point) {
2059
+ pointOptions.zIndex = H.pointCameraDistance(point, this.chart);
2060
+ }
2061
+ return pointOptions;
2062
+ });
2063
+
2064
+
2065
+ wrap(Point.prototype, 'applyOptions', function(proceed) {
2066
+ var point = proceed.apply(this, [].slice.call(arguments, 1));
2067
+
2068
+ if (this.series.chart.is3d() && point.z === undefined) {
2069
+ point.z = 0;
2070
+ }
2071
+ return point;
2072
+ });
2073
+
2074
+ }(Highcharts));
2075
+ (function(H) {
2076
+ /**
2077
+ * (c) 2010-2016 Torstein Honsi
2078
+ *
2079
+ * License: www.highcharts.com/license
2080
+ */
2081
+ 'use strict';
2082
+
2083
+
2084
+ }(Highcharts));
2085
+ }));