highcharts_rails 0.1.0

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