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