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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +106 -0
- data/Rakefile +6 -0
- data/highcharts_rails.gemspec +27 -0
- data/lib/highcharts_rails/version.rb +3 -0
- data/lib/highcharts_rails.rb +8 -0
- data/vendor/assets/javascripts/highcharts-3d.src.js +2139 -0
- data/vendor/assets/javascripts/highcharts-more.src.js +2982 -0
- data/vendor/assets/javascripts/highcharts.src.js +22947 -0
- data/vendor/assets/javascripts/js/highcharts-3d.src.js +2085 -0
- data/vendor/assets/javascripts/js/highcharts-more.src.js +2820 -0
- data/vendor/assets/javascripts/js/highcharts.src.js +20917 -0
- data/vendor/assets/javascripts/js/modules/accessibility.src.js +1072 -0
- data/vendor/assets/javascripts/js/modules/annotations.src.js +408 -0
- data/vendor/assets/javascripts/js/modules/boost.src.js +652 -0
- data/vendor/assets/javascripts/js/modules/broken-axis.src.js +338 -0
- data/vendor/assets/javascripts/js/modules/data.src.js +981 -0
- data/vendor/assets/javascripts/js/modules/drilldown.src.js +756 -0
- data/vendor/assets/javascripts/js/modules/exporting.src.js +953 -0
- data/vendor/assets/javascripts/js/modules/funnel.src.js +290 -0
- data/vendor/assets/javascripts/js/modules/gantt.src.js +791 -0
- data/vendor/assets/javascripts/js/modules/grid-axis.src.js +545 -0
- data/vendor/assets/javascripts/js/modules/heatmap.src.js +798 -0
- data/vendor/assets/javascripts/js/modules/no-data-to-display.src.js +150 -0
- data/vendor/assets/javascripts/js/modules/offline-exporting.src.js +492 -0
- data/vendor/assets/javascripts/js/modules/overlapping-datalabels.src.js +164 -0
- data/vendor/assets/javascripts/js/modules/series-label.src.js +606 -0
- data/vendor/assets/javascripts/js/modules/solid-gauge.src.js +305 -0
- data/vendor/assets/javascripts/js/modules/treemap.src.js +881 -0
- data/vendor/assets/javascripts/js/modules/xrange-series.src.js +254 -0
- data/vendor/assets/javascripts/js/themes/dark-blue.js +317 -0
- data/vendor/assets/javascripts/js/themes/dark-green.js +314 -0
- data/vendor/assets/javascripts/js/themes/dark-unica.js +243 -0
- data/vendor/assets/javascripts/js/themes/gray.js +326 -0
- data/vendor/assets/javascripts/js/themes/grid-light.js +99 -0
- data/vendor/assets/javascripts/js/themes/grid.js +131 -0
- data/vendor/assets/javascripts/js/themes/sand-signika.js +129 -0
- data/vendor/assets/javascripts/js/themes/skies.js +112 -0
- data/vendor/assets/javascripts/lib/canvg.src.js +3073 -0
- data/vendor/assets/javascripts/lib/jspdf.src.js +3031 -0
- data/vendor/assets/javascripts/lib/rgbcolor.src.js +299 -0
- data/vendor/assets/javascripts/lib/svg2pdf.src.js +1451 -0
- data/vendor/assets/javascripts/modules/accessibility.src.js +1072 -0
- data/vendor/assets/javascripts/modules/annotations.src.js +408 -0
- data/vendor/assets/javascripts/modules/boost.src.js +652 -0
- data/vendor/assets/javascripts/modules/broken-axis.src.js +338 -0
- data/vendor/assets/javascripts/modules/data.src.js +981 -0
- data/vendor/assets/javascripts/modules/drilldown.src.js +797 -0
- data/vendor/assets/javascripts/modules/exporting.src.js +882 -0
- data/vendor/assets/javascripts/modules/funnel.src.js +304 -0
- data/vendor/assets/javascripts/modules/gantt.src.js +815 -0
- data/vendor/assets/javascripts/modules/grid-axis.src.js +547 -0
- data/vendor/assets/javascripts/modules/heatmap.src.js +810 -0
- data/vendor/assets/javascripts/modules/no-data-to-display.src.js +161 -0
- data/vendor/assets/javascripts/modules/offline-exporting.src.js +492 -0
- data/vendor/assets/javascripts/modules/overlapping-datalabels.src.js +164 -0
- data/vendor/assets/javascripts/modules/series-label.src.js +606 -0
- data/vendor/assets/javascripts/modules/solid-gauge.src.js +316 -0
- data/vendor/assets/javascripts/modules/treemap.src.js +935 -0
- data/vendor/assets/javascripts/modules/xrange-series.src.js +276 -0
- data/vendor/assets/javascripts/themes/dark-blue.js +317 -0
- data/vendor/assets/javascripts/themes/dark-green.js +314 -0
- data/vendor/assets/javascripts/themes/dark-unica.js +243 -0
- data/vendor/assets/javascripts/themes/gray.js +326 -0
- data/vendor/assets/javascripts/themes/grid-light.js +99 -0
- data/vendor/assets/javascripts/themes/grid.js +131 -0
- data/vendor/assets/javascripts/themes/sand-signika.js +129 -0
- data/vendor/assets/javascripts/themes/skies.js +112 -0
- data/vendor/assets/stylesheets/highcharts.scss +610 -0
- 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
|
+
}));
|