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