highcharts-rails 4.1.9 → 4.1.10
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 +55 -0
- data/app/assets/images/highcharts/search.png +0 -0
- data/app/assets/javascripts/highcharts.js +18962 -18796
- data/app/assets/javascripts/highcharts/adapters/standalone-framework.js +152 -131
- data/app/assets/javascripts/highcharts/highcharts-3d.js +1702 -1561
- data/app/assets/javascripts/highcharts/highcharts-more.js +2655 -2639
- data/app/assets/javascripts/highcharts/modules/boost.js +72 -35
- data/app/assets/javascripts/highcharts/modules/broken-axis.js +45 -32
- data/app/assets/javascripts/highcharts/modules/canvas-tools.js +8 -7
- data/app/assets/javascripts/highcharts/modules/data.js +646 -642
- data/app/assets/javascripts/highcharts/modules/drilldown.js +15 -11
- data/app/assets/javascripts/highcharts/modules/exporting.js +17 -12
- data/app/assets/javascripts/highcharts/modules/funnel.js +19 -12
- data/app/assets/javascripts/highcharts/modules/heatmap.js +702 -696
- data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +10 -4
- data/app/assets/javascripts/highcharts/modules/offline-exporting.js +241 -238
- data/app/assets/javascripts/highcharts/modules/solid-gauge.js +12 -9
- data/app/assets/javascripts/highcharts/modules/treemap.js +67 -86
- data/app/assets/javascripts/highcharts/themes/grid-light.js +1 -1
- data/app/assets/javascripts/highcharts/themes/sand-signika.js +1 -1
- data/lib/highcharts/version.rb +1 -1
- metadata +3 -2
@@ -1,26 +1,44 @@
|
|
1
1
|
/**
|
2
|
-
* @license Highcharts JS v4.1.
|
2
|
+
* @license Highcharts JS v4.1.10 (2015-12-07)
|
3
3
|
*
|
4
4
|
* Standalone Highcharts Framework
|
5
5
|
*
|
6
6
|
* License: MIT License
|
7
7
|
*/
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
(function (root, factory) {
|
10
|
+
if (typeof module === 'object' && module.exports) {
|
11
|
+
module.exports = root.document ?
|
12
|
+
factory(root) :
|
13
|
+
function (w) {
|
14
|
+
return factory(w);
|
15
|
+
};
|
16
|
+
} else {
|
17
|
+
root.HighchartsAdapter = factory();
|
18
|
+
}
|
19
|
+
}(typeof window !== 'undefined' ? window : this, function (w) {
|
12
20
|
|
13
21
|
var UNDEFINED,
|
14
|
-
|
22
|
+
win = w || window,
|
23
|
+
doc = win.document,
|
15
24
|
emptyArray = [],
|
25
|
+
_getStyle,
|
16
26
|
timers = [],
|
17
27
|
animSetters = {},
|
28
|
+
HighchartsAdapter,
|
18
29
|
Fx;
|
19
30
|
|
20
31
|
Math.easeInOutSine = function (t, b, c, d) {
|
21
32
|
return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
|
22
33
|
};
|
23
34
|
|
35
|
+
/**
|
36
|
+
* Internal method to return CSS value for given element and property
|
37
|
+
*/
|
38
|
+
_getStyle = function (el, prop) {
|
39
|
+
var style = win.getComputedStyle(el, undefined);
|
40
|
+
return style && style.getPropertyValue(prop);
|
41
|
+
};
|
24
42
|
|
25
43
|
|
26
44
|
/**
|
@@ -70,120 +88,118 @@ function augment(obj) {
|
|
70
88
|
}
|
71
89
|
|
72
90
|
if (!obj.HCExtended) {
|
73
|
-
|
74
|
-
HCExtended: true,
|
91
|
+
obj.HCExtended = true;
|
75
92
|
|
76
|
-
|
93
|
+
obj.HCEvents = {};
|
77
94
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
95
|
+
obj.bind = function (name, fn) {
|
96
|
+
var el = this,
|
97
|
+
events = this.HCEvents,
|
98
|
+
wrappedFn;
|
82
99
|
|
83
|
-
|
84
|
-
|
85
|
-
|
100
|
+
// handle DOM events in modern browsers
|
101
|
+
if (el.addEventListener) {
|
102
|
+
el.addEventListener(name, fn, false);
|
86
103
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
104
|
+
// handle old IE implementation
|
105
|
+
} else if (el.attachEvent) {
|
106
|
+
|
107
|
+
wrappedFn = function (e) {
|
108
|
+
e.target = e.srcElement || win; // #2820
|
109
|
+
fn.call(el, e);
|
110
|
+
};
|
94
111
|
|
95
|
-
|
96
|
-
|
97
|
-
|
112
|
+
if (!el.HCProxiedMethods) {
|
113
|
+
el.HCProxiedMethods = {};
|
114
|
+
}
|
98
115
|
|
99
|
-
|
100
|
-
|
116
|
+
// link wrapped fn with original fn, so we can get this in removeEvent
|
117
|
+
el.HCProxiedMethods[fn.toString()] = wrappedFn;
|
101
118
|
|
102
|
-
|
103
|
-
|
119
|
+
el.attachEvent('on' + name, wrappedFn);
|
120
|
+
}
|
104
121
|
|
105
122
|
|
106
|
-
|
107
|
-
|
108
|
-
|
123
|
+
if (events[name] === UNDEFINED) {
|
124
|
+
events[name] = [];
|
125
|
+
}
|
109
126
|
|
110
|
-
|
111
|
-
|
127
|
+
events[name].push(fn);
|
128
|
+
};
|
112
129
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
}
|
130
|
-
} else {
|
131
|
-
removeAllEvents(this, name);
|
132
|
-
this.HCEvents[name] = [];
|
130
|
+
obj.unbind = function (name, fn) {
|
131
|
+
var events,
|
132
|
+
index;
|
133
|
+
|
134
|
+
if (name) {
|
135
|
+
events = this.HCEvents[name] || [];
|
136
|
+
if (fn) {
|
137
|
+
index = HighchartsAdapter.inArray(fn, events);
|
138
|
+
if (index > -1) {
|
139
|
+
events.splice(index, 1);
|
140
|
+
this.HCEvents[name] = events;
|
141
|
+
}
|
142
|
+
if (this.removeEventListener) {
|
143
|
+
removeOneEvent(this, name, fn);
|
144
|
+
} else if (this.attachEvent) {
|
145
|
+
IERemoveOneEvent(this, name, fn);
|
133
146
|
}
|
134
147
|
} else {
|
135
|
-
removeAllEvents(this);
|
136
|
-
this.HCEvents =
|
148
|
+
removeAllEvents(this, name);
|
149
|
+
this.HCEvents[name] = [];
|
137
150
|
}
|
138
|
-
}
|
151
|
+
} else {
|
152
|
+
removeAllEvents(this);
|
153
|
+
this.HCEvents = {};
|
154
|
+
}
|
155
|
+
};
|
139
156
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
157
|
+
obj.trigger = function (name, args) {
|
158
|
+
var events = this.HCEvents[name] || [],
|
159
|
+
target = this,
|
160
|
+
len = events.length,
|
161
|
+
i,
|
162
|
+
preventDefault,
|
163
|
+
fn;
|
164
|
+
|
165
|
+
// Attach a simple preventDefault function to skip default handler if called
|
166
|
+
preventDefault = function () {
|
167
|
+
args.defaultPrevented = true;
|
168
|
+
};
|
169
|
+
|
170
|
+
for (i = 0; i < len; i++) {
|
171
|
+
fn = events[i];
|
155
172
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
173
|
+
// args is never null here
|
174
|
+
if (args.stopped) {
|
175
|
+
return;
|
176
|
+
}
|
160
177
|
|
161
|
-
|
162
|
-
|
178
|
+
args.preventDefault = preventDefault;
|
179
|
+
args.target = target;
|
163
180
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
181
|
+
// If the type is not set, we're running a custom event (#2297). If it is set,
|
182
|
+
// we're running a browser event, and setting it will cause en error in
|
183
|
+
// IE8 (#2465).
|
184
|
+
if (!args.type) {
|
185
|
+
args.type = name;
|
186
|
+
}
|
187
|
+
|
171
188
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
}
|
189
|
+
|
190
|
+
// If the event handler return false, prevent the default handler from executing
|
191
|
+
if (fn.call(this, args) === false) {
|
192
|
+
args.preventDefault();
|
177
193
|
}
|
178
194
|
}
|
179
|
-
}
|
195
|
+
};
|
180
196
|
}
|
181
197
|
|
182
198
|
return obj;
|
183
199
|
}
|
184
200
|
|
185
201
|
|
186
|
-
|
202
|
+
HighchartsAdapter = {
|
187
203
|
|
188
204
|
/**
|
189
205
|
* Initialize the adapter. This is run once as Highcharts is first run.
|
@@ -195,34 +211,35 @@ return {
|
|
195
211
|
* support is not needed.
|
196
212
|
*/
|
197
213
|
if (!doc.defaultView) {
|
198
|
-
|
214
|
+
_getStyle = function (el, prop) {
|
199
215
|
var val;
|
200
216
|
if (el.style[prop]) {
|
201
217
|
return el.style[prop];
|
202
|
-
}
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
218
|
+
}
|
219
|
+
if (prop === 'opacity') {
|
220
|
+
prop = 'filter';
|
221
|
+
}
|
222
|
+
|
223
|
+
val = el.currentStyle[prop.replace(/\-(\w)/g, function (a, b) {
|
224
|
+
return b.toUpperCase();
|
225
|
+
})];
|
226
|
+
if (prop === 'filter') {
|
227
|
+
val = val.replace(
|
228
|
+
/alpha\(opacity=([0-9]+)\)/,
|
229
|
+
function (a, b) {
|
230
|
+
return b / 100;
|
231
|
+
}
|
232
|
+
);
|
233
|
+
}
|
234
|
+
|
235
|
+
return val === '' ? 1 : val;
|
219
236
|
};
|
220
237
|
this.adapterRun = function (elem, method) {
|
221
238
|
var alias = { width: 'clientWidth', height: 'clientHeight' }[method];
|
222
239
|
|
223
240
|
if (alias) {
|
224
241
|
elem.style.zoom = 1;
|
225
|
-
return elem[alias] - 2 * parseInt(
|
242
|
+
return elem[alias] - 2 * parseInt(_getStyle(elem, 'padding'), 10);
|
226
243
|
}
|
227
244
|
};
|
228
245
|
}
|
@@ -259,13 +276,13 @@ return {
|
|
259
276
|
}
|
260
277
|
|
261
278
|
if (!Array.prototype.filter) {
|
262
|
-
this.grep = function (elements,
|
279
|
+
this.grep = function (elements, fn) {
|
263
280
|
var ret = [],
|
264
281
|
i = 0,
|
265
282
|
length = elements.length;
|
266
283
|
|
267
284
|
for (; i < length; i++) {
|
268
|
-
if (!!
|
285
|
+
if (!!fn(elements[i], i)) {
|
269
286
|
ret.push(elements[i]);
|
270
287
|
}
|
271
288
|
}
|
@@ -291,7 +308,8 @@ return {
|
|
291
308
|
var styles,
|
292
309
|
paths = this.paths,
|
293
310
|
elem = this.elem,
|
294
|
-
elemelem = elem.element
|
311
|
+
elemelem = elem.element,
|
312
|
+
prop; // if destroyed, it is null
|
295
313
|
|
296
314
|
// Animation setter defined from outside
|
297
315
|
if (animSetters[this.prop]) {
|
@@ -307,11 +325,13 @@ return {
|
|
307
325
|
elem.attr(this.prop, this.now);
|
308
326
|
}
|
309
327
|
|
310
|
-
// HTML styles
|
328
|
+
// HTML styles, raw HTML content like container size
|
311
329
|
} else {
|
312
330
|
styles = {};
|
313
331
|
styles[this.prop] = this.now + this.unit;
|
314
|
-
|
332
|
+
for (prop in styles) {
|
333
|
+
elem.style[prop] = styles[prop];
|
334
|
+
}
|
315
335
|
}
|
316
336
|
|
317
337
|
if (this.options.step) {
|
@@ -405,6 +425,7 @@ return {
|
|
405
425
|
fx,
|
406
426
|
args,
|
407
427
|
name,
|
428
|
+
key,
|
408
429
|
PX = 'px';
|
409
430
|
|
410
431
|
if (typeof opt !== 'object' || opt === null) {
|
@@ -419,7 +440,10 @@ return {
|
|
419
440
|
opt.duration = 400;
|
420
441
|
}
|
421
442
|
opt.easing = Math[opt.easing] || Math.easeInOutSine;
|
422
|
-
opt.curAnim =
|
443
|
+
opt.curAnim = {};
|
444
|
+
for (key in prop) {
|
445
|
+
opt.curAnim[key] = prop[key];
|
446
|
+
}
|
423
447
|
|
424
448
|
for (name in prop) {
|
425
449
|
fx = new Fx(el, opt, name);
|
@@ -437,7 +461,7 @@ return {
|
|
437
461
|
} else if (el.attr) {
|
438
462
|
start = el.attr(name);
|
439
463
|
} else {
|
440
|
-
start = parseFloat(
|
464
|
+
start = parseFloat(_getStyle(el, name)) || 0;
|
441
465
|
if (name !== 'opacity') {
|
442
466
|
unit = PX;
|
443
467
|
}
|
@@ -454,13 +478,6 @@ return {
|
|
454
478
|
};
|
455
479
|
},
|
456
480
|
|
457
|
-
/**
|
458
|
-
* Internal method to return CSS value for given element and property
|
459
|
-
*/
|
460
|
-
_getStyle: function (el, prop) {
|
461
|
-
return window.getComputedStyle(el, undefined).getPropertyValue(prop);
|
462
|
-
},
|
463
|
-
|
464
481
|
/**
|
465
482
|
* Add an animation setter for a specific property
|
466
483
|
*/
|
@@ -497,7 +514,7 @@ return {
|
|
497
514
|
* A direct link to adapter methods
|
498
515
|
*/
|
499
516
|
adapterRun: function (elem, method) {
|
500
|
-
return parseInt(
|
517
|
+
return parseInt(_getStyle(elem, method), 10);
|
501
518
|
},
|
502
519
|
|
503
520
|
/**
|
@@ -528,8 +545,8 @@ return {
|
|
528
545
|
box = el.getBoundingClientRect();
|
529
546
|
|
530
547
|
return {
|
531
|
-
top: box.top + (
|
532
|
-
left: box.left + (
|
548
|
+
top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
|
549
|
+
left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
|
533
550
|
};
|
534
551
|
},
|
535
552
|
|
@@ -551,14 +568,17 @@ return {
|
|
551
568
|
* Fire an event on a custom object
|
552
569
|
*/
|
553
570
|
fireEvent: function (el, type, eventArguments, defaultFunction) {
|
554
|
-
var e
|
571
|
+
var e,
|
572
|
+
key;
|
555
573
|
|
556
574
|
if (doc.createEvent && (el.dispatchEvent || el.fireEvent)) {
|
557
575
|
e = doc.createEvent('Events');
|
558
576
|
e.initEvent(type, true, true);
|
559
577
|
e.target = el;
|
560
578
|
|
561
|
-
|
579
|
+
for (key in eventArguments) {
|
580
|
+
e[key] = eventArguments[key];
|
581
|
+
}
|
562
582
|
|
563
583
|
if (el.dispatchEvent) {
|
564
584
|
el.dispatchEvent(e);
|
@@ -611,4 +631,5 @@ return {
|
|
611
631
|
return Array.prototype.forEach.call(arr, fn);
|
612
632
|
}
|
613
633
|
};
|
614
|
-
|
634
|
+
return HighchartsAdapter;
|
635
|
+
}));
|
@@ -2,1569 +2,1710 @@
|
|
2
2
|
// @compilation_level SIMPLE_OPTIMIZATIONS
|
3
3
|
|
4
4
|
/**
|
5
|
-
* @license Highcharts JS v4.1.
|
5
|
+
* @license Highcharts JS v4.1.10 (2015-12-07)
|
6
6
|
*
|
7
|
-
*
|
7
|
+
* 3D features for Highcharts JS
|
8
8
|
*
|
9
|
-
*
|
9
|
+
* @license: www.highcharts.com/license
|
10
10
|
*/
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
/**
|
20
|
-
* Mathematical Functionility
|
21
|
-
*/
|
22
|
-
var PI = Math.PI,
|
23
|
-
deg2rad = (PI / 180), // degrees to radians
|
24
|
-
sin = Math.sin,
|
25
|
-
cos = Math.cos,
|
26
|
-
pick = Highcharts.pick,
|
27
|
-
round = Math.round;
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Transforms a given array of points according to the angles in chart.options.
|
31
|
-
* Parameters:
|
32
|
-
* - points: the array of points
|
33
|
-
* - chart: the chart
|
34
|
-
* - insidePlotArea: wether to verifiy the points are inside the plotArea
|
35
|
-
* Returns:
|
36
|
-
* - an array of transformed points
|
37
|
-
*/
|
38
|
-
function perspective(points, chart, insidePlotArea) {
|
39
|
-
var options3d = chart.options.chart.options3d,
|
40
|
-
inverted = false,
|
41
|
-
origin;
|
42
|
-
|
43
|
-
if (insidePlotArea) {
|
44
|
-
inverted = chart.inverted;
|
45
|
-
origin = {
|
46
|
-
x: chart.plotWidth / 2,
|
47
|
-
y: chart.plotHeight / 2,
|
48
|
-
z: options3d.depth / 2,
|
49
|
-
vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
|
50
|
-
};
|
51
|
-
} else {
|
52
|
-
origin = {
|
53
|
-
x: chart.plotLeft + (chart.plotWidth / 2),
|
54
|
-
y: chart.plotTop + (chart.plotHeight / 2),
|
55
|
-
z: options3d.depth / 2,
|
56
|
-
vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
|
57
|
-
};
|
58
|
-
}
|
59
|
-
|
60
|
-
var result = [],
|
61
|
-
xe = origin.x,
|
62
|
-
ye = origin.y,
|
63
|
-
ze = origin.z,
|
64
|
-
vd = origin.vd,
|
65
|
-
angle1 = deg2rad * (inverted ? options3d.beta : -options3d.beta),
|
66
|
-
angle2 = deg2rad * (inverted ? -options3d.alpha : options3d.alpha),
|
67
|
-
s1 = sin(angle1),
|
68
|
-
c1 = cos(angle1),
|
69
|
-
s2 = sin(angle2),
|
70
|
-
c2 = cos(angle2);
|
71
|
-
|
72
|
-
var x, y, z, px, py, pz;
|
73
|
-
|
74
|
-
// Transform each point
|
75
|
-
Highcharts.each(points, function (point) {
|
76
|
-
x = (inverted ? point.y : point.x) - xe;
|
77
|
-
y = (inverted ? point.x : point.y) - ye;
|
78
|
-
z = (point.z || 0) - ze;
|
79
|
-
|
80
|
-
//Apply 3-D rotation
|
81
|
-
px = c1 * x - s1 * z;
|
82
|
-
py = -s1 * s2 * x - c1 * s2 * z + c2 * y;
|
83
|
-
pz = s1 * c2 * x + c1 * c2 * z + s2 * y;
|
84
|
-
|
85
|
-
//Apply perspective
|
86
|
-
if ((vd > 0) && (vd < Number.POSITIVE_INFINITY)) {
|
87
|
-
px = px * (vd / (pz + ze + vd));
|
88
|
-
py = py * (vd / (pz + ze + vd));
|
89
|
-
}
|
90
|
-
|
91
|
-
//Apply translation
|
92
|
-
px = px + xe;
|
93
|
-
py = py + ye;
|
94
|
-
pz = pz + ze;
|
95
|
-
|
96
|
-
result.push({
|
97
|
-
x: (inverted ? py : px),
|
98
|
-
y: (inverted ? px : py),
|
99
|
-
z: pz
|
100
|
-
});
|
101
|
-
});
|
102
|
-
return result;
|
103
|
-
}
|
104
|
-
// Make function acessible to plugins
|
105
|
-
Highcharts.perspective = perspective;
|
106
|
-
/***
|
107
|
-
EXTENSION TO THE SVG-RENDERER TO ENABLE 3D SHAPES
|
108
|
-
***/
|
109
|
-
////// HELPER METHODS //////
|
110
|
-
var dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2);
|
111
|
-
|
112
|
-
function defined(obj) {
|
113
|
-
return obj !== undefined && obj !== null;
|
114
|
-
}
|
115
|
-
|
116
|
-
//Shoelace algorithm -- http://en.wikipedia.org/wiki/Shoelace_formula
|
117
|
-
function shapeArea(vertexes) {
|
118
|
-
var area = 0,
|
119
|
-
i,
|
120
|
-
j;
|
121
|
-
for (i = 0; i < vertexes.length; i++) {
|
122
|
-
j = (i + 1) % vertexes.length;
|
123
|
-
area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
|
124
|
-
}
|
125
|
-
return area / 2;
|
126
|
-
}
|
127
|
-
|
128
|
-
function averageZ(vertexes) {
|
129
|
-
var z = 0,
|
130
|
-
i;
|
131
|
-
for (i = 0; i < vertexes.length; i++) {
|
132
|
-
z += vertexes[i].z;
|
133
|
-
}
|
134
|
-
return vertexes.length ? z / vertexes.length : 0;
|
135
|
-
}
|
136
|
-
|
137
|
-
/** Method to construct a curved path
|
138
|
-
* Can 'wrap' around more then 180 degrees
|
139
|
-
*/
|
140
|
-
function curveTo(cx, cy, rx, ry, start, end, dx, dy) {
|
141
|
-
var result = [];
|
142
|
-
if ((end > start) && (end - start > PI / 2 + 0.0001)) {
|
143
|
-
result = result.concat(curveTo(cx, cy, rx, ry, start, start + (PI / 2), dx, dy));
|
144
|
-
result = result.concat(curveTo(cx, cy, rx, ry, start + (PI / 2), end, dx, dy));
|
145
|
-
return result;
|
146
|
-
} else if ((end < start) && (start - end > PI / 2 + 0.0001)) {
|
147
|
-
result = result.concat(curveTo(cx, cy, rx, ry, start, start - (PI / 2), dx, dy));
|
148
|
-
result = result.concat(curveTo(cx, cy, rx, ry, start - (PI / 2), end, dx, dy));
|
149
|
-
return result;
|
150
|
-
} else {
|
151
|
-
var arcAngle = end - start;
|
152
|
-
return [
|
153
|
-
'C',
|
154
|
-
cx + (rx * cos(start)) - ((rx * dFactor * arcAngle) * sin(start)) + dx,
|
155
|
-
cy + (ry * sin(start)) + ((ry * dFactor * arcAngle) * cos(start)) + dy,
|
156
|
-
cx + (rx * cos(end)) + ((rx * dFactor * arcAngle) * sin(end)) + dx,
|
157
|
-
cy + (ry * sin(end)) - ((ry * dFactor * arcAngle) * cos(end)) + dy,
|
158
|
-
|
159
|
-
cx + (rx * cos(end)) + dx,
|
160
|
-
cy + (ry * sin(end)) + dy
|
161
|
-
];
|
162
|
-
}
|
163
|
-
}
|
164
|
-
|
165
|
-
Highcharts.SVGRenderer.prototype.toLinePath = function (points, closed) {
|
166
|
-
var result = [];
|
167
|
-
|
168
|
-
// Put "L x y" for each point
|
169
|
-
Highcharts.each(points, function (point) {
|
170
|
-
result.push('L', point.x, point.y);
|
171
|
-
});
|
172
|
-
|
173
|
-
if (points.length) {
|
174
|
-
// Set the first element to M
|
175
|
-
result[0] = 'M';
|
176
|
-
|
177
|
-
// If it is a closed line, add Z
|
178
|
-
if (closed) {
|
179
|
-
result.push('Z');
|
180
|
-
}
|
181
|
-
}
|
182
|
-
|
183
|
-
return result;
|
184
|
-
};
|
185
|
-
|
186
|
-
////// CUBOIDS //////
|
187
|
-
Highcharts.SVGRenderer.prototype.cuboid = function (shapeArgs) {
|
188
|
-
|
189
|
-
var result = this.g(),
|
190
|
-
paths = this.cuboidPath(shapeArgs);
|
191
|
-
|
192
|
-
// create the 3 sides
|
193
|
-
result.front = this.path(paths[0]).attr({zIndex: paths[3], 'stroke-linejoin': 'round'}).add(result);
|
194
|
-
result.top = this.path(paths[1]).attr({zIndex: paths[4], 'stroke-linejoin': 'round'}).add(result);
|
195
|
-
result.side = this.path(paths[2]).attr({zIndex: paths[5], 'stroke-linejoin': 'round'}).add(result);
|
196
|
-
|
197
|
-
// apply the fill everywhere, the top a bit brighter, the side a bit darker
|
198
|
-
result.fillSetter = function (color) {
|
199
|
-
var c0 = color,
|
200
|
-
c1 = Highcharts.Color(color).brighten(0.1).get(),
|
201
|
-
c2 = Highcharts.Color(color).brighten(-0.1).get();
|
202
|
-
|
203
|
-
this.front.attr({fill: c0});
|
204
|
-
this.top.attr({fill: c1});
|
205
|
-
this.side.attr({fill: c2});
|
206
|
-
|
207
|
-
this.color = color;
|
208
|
-
return this;
|
209
|
-
};
|
210
|
-
|
211
|
-
// apply opacaity everywhere
|
212
|
-
result.opacitySetter = function (opacity) {
|
213
|
-
this.front.attr({opacity: opacity});
|
214
|
-
this.top.attr({opacity: opacity});
|
215
|
-
this.side.attr({opacity: opacity});
|
216
|
-
return this;
|
217
|
-
};
|
218
|
-
|
219
|
-
result.attr = function (args) {
|
220
|
-
if (args.shapeArgs || defined(args.x)) {
|
221
|
-
var shapeArgs = args.shapeArgs || args;
|
222
|
-
var paths = this.renderer.cuboidPath(shapeArgs);
|
223
|
-
this.front.attr({d: paths[0], zIndex: paths[3]});
|
224
|
-
this.top.attr({d: paths[1], zIndex: paths[4]});
|
225
|
-
this.side.attr({d: paths[2], zIndex: paths[5]});
|
226
|
-
} else {
|
227
|
-
Highcharts.SVGElement.prototype.attr.call(this, args);
|
228
|
-
}
|
229
|
-
|
230
|
-
return this;
|
231
|
-
};
|
232
|
-
|
233
|
-
result.animate = function (args, duration, complete) {
|
234
|
-
if (defined(args.x) && defined(args.y)) {
|
235
|
-
var paths = this.renderer.cuboidPath(args);
|
236
|
-
this.front.attr({zIndex: paths[3]}).animate({d: paths[0]}, duration, complete);
|
237
|
-
this.top.attr({zIndex: paths[4]}).animate({d: paths[1]}, duration, complete);
|
238
|
-
this.side.attr({zIndex: paths[5]}).animate({d: paths[2]}, duration, complete);
|
239
|
-
} else if (args.opacity) {
|
240
|
-
this.front.animate(args, duration, complete);
|
241
|
-
this.top.animate(args, duration, complete);
|
242
|
-
this.side.animate(args, duration, complete);
|
243
|
-
} else {
|
244
|
-
Highcharts.SVGElement.prototype.animate.call(this, args, duration, complete);
|
245
|
-
}
|
246
|
-
return this;
|
247
|
-
};
|
248
|
-
|
249
|
-
// destroy all children
|
250
|
-
result.destroy = function () {
|
251
|
-
this.front.destroy();
|
252
|
-
this.top.destroy();
|
253
|
-
this.side.destroy();
|
254
|
-
|
255
|
-
return null;
|
256
|
-
};
|
257
|
-
|
258
|
-
// Apply the Z index to the cuboid group
|
259
|
-
result.attr({ zIndex: -paths[3] });
|
260
|
-
|
261
|
-
return result;
|
262
|
-
};
|
263
|
-
|
12
|
+
(function (factory) {
|
13
|
+
if (typeof module === 'object' && module.exports) {
|
14
|
+
module.exports = factory;
|
15
|
+
} else {
|
16
|
+
factory(Highcharts);
|
17
|
+
}
|
18
|
+
}(function (Highcharts) {
|
264
19
|
/**
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
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
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
//
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
//
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
};
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
}
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
}
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
}
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
};
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
}
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1197
|
-
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
}
|
1208
|
-
|
1209
|
-
Highcharts.wrap(Highcharts.
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
}
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1339
|
-
|
1340
|
-
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
}
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1418
|
-
|
1419
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1435
|
-
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1442
|
-
|
1443
|
-
|
1444
|
-
|
1445
|
-
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
//
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1486
|
-
|
1487
|
-
|
1488
|
-
|
1489
|
-
|
1490
|
-
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1504
|
-
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
|
1521
|
-
|
1522
|
-
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
if (
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1556
|
-
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
20
|
+
Shorthands for often used function
|
21
|
+
*/
|
22
|
+
var each = Highcharts.each,
|
23
|
+
extend = Highcharts.extend,
|
24
|
+
inArray = Highcharts.inArray,
|
25
|
+
merge = Highcharts.merge,
|
26
|
+
pick = Highcharts.pick,
|
27
|
+
wrap = Highcharts.wrap;
|
28
|
+
/**
|
29
|
+
* Mathematical Functionility
|
30
|
+
*/
|
31
|
+
var PI = Math.PI,
|
32
|
+
deg2rad = (PI / 180), // degrees to radians
|
33
|
+
sin = Math.sin,
|
34
|
+
cos = Math.cos,
|
35
|
+
round = Math.round;
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Transforms a given array of points according to the angles in chart.options.
|
39
|
+
* Parameters:
|
40
|
+
* - points: the array of points
|
41
|
+
* - chart: the chart
|
42
|
+
* - insidePlotArea: wether to verifiy the points are inside the plotArea
|
43
|
+
* Returns:
|
44
|
+
* - an array of transformed points
|
45
|
+
*/
|
46
|
+
function perspective(points, chart, insidePlotArea) {
|
47
|
+
var options3d = chart.options.chart.options3d,
|
48
|
+
inverted = false,
|
49
|
+
origin;
|
50
|
+
|
51
|
+
if (insidePlotArea) {
|
52
|
+
inverted = chart.inverted;
|
53
|
+
origin = {
|
54
|
+
x: chart.plotWidth / 2,
|
55
|
+
y: chart.plotHeight / 2,
|
56
|
+
z: options3d.depth / 2,
|
57
|
+
vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
|
58
|
+
};
|
59
|
+
} else {
|
60
|
+
origin = {
|
61
|
+
x: chart.plotLeft + (chart.plotWidth / 2),
|
62
|
+
y: chart.plotTop + (chart.plotHeight / 2),
|
63
|
+
z: options3d.depth / 2,
|
64
|
+
vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
|
65
|
+
};
|
66
|
+
}
|
67
|
+
|
68
|
+
var result = [],
|
69
|
+
xe = origin.x,
|
70
|
+
ye = origin.y,
|
71
|
+
ze = origin.z,
|
72
|
+
vd = origin.vd,
|
73
|
+
angle1 = deg2rad * (inverted ? options3d.beta : -options3d.beta),
|
74
|
+
angle2 = deg2rad * (inverted ? -options3d.alpha : options3d.alpha),
|
75
|
+
s1 = sin(angle1),
|
76
|
+
c1 = cos(angle1),
|
77
|
+
s2 = sin(angle2),
|
78
|
+
c2 = cos(angle2);
|
79
|
+
|
80
|
+
var x, y, z, px, py, pz;
|
81
|
+
|
82
|
+
// Transform each point
|
83
|
+
each(points, function (point) {
|
84
|
+
x = (inverted ? point.y : point.x) - xe;
|
85
|
+
y = (inverted ? point.x : point.y) - ye;
|
86
|
+
z = (point.z || 0) - ze;
|
87
|
+
|
88
|
+
// Apply 3-D rotation
|
89
|
+
// Euler Angles (XYZ): cosA = cos(Alfa|Roll), cosB = cos(Beta|Pitch), cosG = cos(Gamma|Yaw)
|
90
|
+
//
|
91
|
+
// Composite rotation:
|
92
|
+
// | cosB * cosG | cosB * sinG | -sinB |
|
93
|
+
// | sinA * sinB * cosG - cosA * sinG | sinA * sinB * sinG + cosA * cosG | sinA * cosB |
|
94
|
+
// | cosA * sinB * cosG + sinA * sinG | cosA * sinB * sinG - sinA * cosG | cosA * cosB |
|
95
|
+
//
|
96
|
+
// Now, Gamma/Yaw is not used (angle=0), so we assume cosG = 1 and sinG = 0, so we get:
|
97
|
+
// | cosB | 0 | - sinB |
|
98
|
+
// | sinA * sinB | cosA | sinA * cosB |
|
99
|
+
// | cosA * sinB | - sinA | cosA * cosB |
|
100
|
+
//
|
101
|
+
// But in browsers, y is reversed, so we get sinA => -sinA. The general result is:
|
102
|
+
// | cosB | 0 | - sinB | | x | | px |
|
103
|
+
// | - sinA * sinB | cosA | - sinA * cosB | x | y | = | py |
|
104
|
+
// | cosA * sinB | sinA | cosA * cosB | | z | | pz |
|
105
|
+
//
|
106
|
+
// Result:
|
107
|
+
px = c1 * x - s1 * z;
|
108
|
+
py = -s1 * s2 * x + c2 * y - c1 * s2 * z;
|
109
|
+
pz = s1 * c2 * x + s2 * y + c1 * c2 * z;
|
110
|
+
|
111
|
+
|
112
|
+
// Apply perspective
|
113
|
+
if ((vd > 0) && (vd < Number.POSITIVE_INFINITY)) {
|
114
|
+
px = px * (vd / (pz + ze + vd));
|
115
|
+
py = py * (vd / (pz + ze + vd));
|
116
|
+
}
|
117
|
+
|
118
|
+
//Apply translation
|
119
|
+
px = px + xe;
|
120
|
+
py = py + ye;
|
121
|
+
pz = pz + ze;
|
122
|
+
|
123
|
+
result.push({
|
124
|
+
x: (inverted ? py : px),
|
125
|
+
y: (inverted ? px : py),
|
126
|
+
z: pz
|
127
|
+
});
|
128
|
+
});
|
129
|
+
return result;
|
130
|
+
}
|
131
|
+
// Make function acessible to plugins
|
132
|
+
Highcharts.perspective = perspective;
|
133
|
+
/***
|
134
|
+
EXTENSION TO THE SVG-RENDERER TO ENABLE 3D SHAPES
|
135
|
+
***/
|
136
|
+
////// HELPER METHODS //////
|
137
|
+
|
138
|
+
var dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2);
|
139
|
+
|
140
|
+
function defined(obj) {
|
141
|
+
return obj !== undefined && obj !== null;
|
142
|
+
}
|
143
|
+
|
144
|
+
//Shoelace algorithm -- http://en.wikipedia.org/wiki/Shoelace_formula
|
145
|
+
function shapeArea(vertexes) {
|
146
|
+
var area = 0,
|
147
|
+
i,
|
148
|
+
j;
|
149
|
+
for (i = 0; i < vertexes.length; i++) {
|
150
|
+
j = (i + 1) % vertexes.length;
|
151
|
+
area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
|
152
|
+
}
|
153
|
+
return area / 2;
|
154
|
+
}
|
155
|
+
|
156
|
+
function averageZ(vertexes) {
|
157
|
+
var z = 0,
|
158
|
+
i;
|
159
|
+
for (i = 0; i < vertexes.length; i++) {
|
160
|
+
z += vertexes[i].z;
|
161
|
+
}
|
162
|
+
return vertexes.length ? z / vertexes.length : 0;
|
163
|
+
}
|
164
|
+
|
165
|
+
/** Method to construct a curved path
|
166
|
+
* Can 'wrap' around more then 180 degrees
|
167
|
+
*/
|
168
|
+
function curveTo(cx, cy, rx, ry, start, end, dx, dy) {
|
169
|
+
var result = [];
|
170
|
+
if ((end > start) && (end - start > PI / 2 + 0.0001)) {
|
171
|
+
result = result.concat(curveTo(cx, cy, rx, ry, start, start + (PI / 2), dx, dy));
|
172
|
+
result = result.concat(curveTo(cx, cy, rx, ry, start + (PI / 2), end, dx, dy));
|
173
|
+
} else if ((end < start) && (start - end > PI / 2 + 0.0001)) {
|
174
|
+
result = result.concat(curveTo(cx, cy, rx, ry, start, start - (PI / 2), dx, dy));
|
175
|
+
result = result.concat(curveTo(cx, cy, rx, ry, start - (PI / 2), end, dx, dy));
|
176
|
+
} else {
|
177
|
+
var arcAngle = end - start;
|
178
|
+
result = [
|
179
|
+
'C',
|
180
|
+
cx + (rx * cos(start)) - ((rx * dFactor * arcAngle) * sin(start)) + dx,
|
181
|
+
cy + (ry * sin(start)) + ((ry * dFactor * arcAngle) * cos(start)) + dy,
|
182
|
+
cx + (rx * cos(end)) + ((rx * dFactor * arcAngle) * sin(end)) + dx,
|
183
|
+
cy + (ry * sin(end)) - ((ry * dFactor * arcAngle) * cos(end)) + dy,
|
184
|
+
|
185
|
+
cx + (rx * cos(end)) + dx,
|
186
|
+
cy + (ry * sin(end)) + dy
|
187
|
+
];
|
188
|
+
}
|
189
|
+
return result;
|
190
|
+
}
|
191
|
+
|
192
|
+
Highcharts.SVGRenderer.prototype.toLinePath = function (points, closed) {
|
193
|
+
var result = [];
|
194
|
+
|
195
|
+
// Put "L x y" for each point
|
196
|
+
Highcharts.each(points, function (point) {
|
197
|
+
result.push('L', point.x, point.y);
|
198
|
+
});
|
199
|
+
|
200
|
+
if (points.length) {
|
201
|
+
// Set the first element to M
|
202
|
+
result[0] = 'M';
|
203
|
+
|
204
|
+
// If it is a closed line, add Z
|
205
|
+
if (closed) {
|
206
|
+
result.push('Z');
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
return result;
|
211
|
+
};
|
212
|
+
|
213
|
+
////// CUBOIDS //////
|
214
|
+
Highcharts.SVGRenderer.prototype.cuboid = function (shapeArgs) {
|
215
|
+
|
216
|
+
var result = this.g(),
|
217
|
+
paths = this.cuboidPath(shapeArgs);
|
218
|
+
|
219
|
+
// create the 3 sides
|
220
|
+
result.front = this.path(paths[0]).attr({ zIndex: paths[3], 'stroke-linejoin': 'round' }).add(result);
|
221
|
+
result.top = this.path(paths[1]).attr({ zIndex: paths[4], 'stroke-linejoin': 'round' }).add(result);
|
222
|
+
result.side = this.path(paths[2]).attr({ zIndex: paths[5], 'stroke-linejoin': 'round' }).add(result);
|
223
|
+
|
224
|
+
// apply the fill everywhere, the top a bit brighter, the side a bit darker
|
225
|
+
result.fillSetter = function (color) {
|
226
|
+
var c0 = color,
|
227
|
+
c1 = Highcharts.Color(color).brighten(0.1).get(),
|
228
|
+
c2 = Highcharts.Color(color).brighten(-0.1).get();
|
229
|
+
|
230
|
+
this.front.attr({ fill: c0 });
|
231
|
+
this.top.attr({ fill: c1 });
|
232
|
+
this.side.attr({ fill: c2 });
|
233
|
+
|
234
|
+
this.color = color;
|
235
|
+
return this;
|
236
|
+
};
|
237
|
+
|
238
|
+
// apply opacaity everywhere
|
239
|
+
result.opacitySetter = function (opacity) {
|
240
|
+
this.front.attr({ opacity: opacity });
|
241
|
+
this.top.attr({ opacity: opacity });
|
242
|
+
this.side.attr({ opacity: opacity });
|
243
|
+
return this;
|
244
|
+
};
|
245
|
+
|
246
|
+
result.attr = function (args) {
|
247
|
+
if (args.shapeArgs || defined(args.x)) {
|
248
|
+
var shapeArgs = args.shapeArgs || args;
|
249
|
+
var paths = this.renderer.cuboidPath(shapeArgs);
|
250
|
+
this.front.attr({ d: paths[0], zIndex: paths[3] });
|
251
|
+
this.top.attr({ d: paths[1], zIndex: paths[4] });
|
252
|
+
this.side.attr({ d: paths[2], zIndex: paths[5] });
|
253
|
+
} else {
|
254
|
+
Highcharts.SVGElement.prototype.attr.call(this, args);
|
255
|
+
}
|
256
|
+
|
257
|
+
return this;
|
258
|
+
};
|
259
|
+
|
260
|
+
result.animate = function (args, duration, complete) {
|
261
|
+
if (defined(args.x) && defined(args.y)) {
|
262
|
+
var paths = this.renderer.cuboidPath(args);
|
263
|
+
this.front.attr({ zIndex: paths[3] }).animate({ d: paths[0] }, duration, complete);
|
264
|
+
this.top.attr({ zIndex: paths[4] }).animate({ d: paths[1] }, duration, complete);
|
265
|
+
this.side.attr({ zIndex: paths[5] }).animate({ d: paths[2] }, duration, complete);
|
266
|
+
} else if (args.opacity) {
|
267
|
+
this.front.animate(args, duration, complete);
|
268
|
+
this.top.animate(args, duration, complete);
|
269
|
+
this.side.animate(args, duration, complete);
|
270
|
+
} else {
|
271
|
+
Highcharts.SVGElement.prototype.animate.call(this, args, duration, complete);
|
272
|
+
}
|
273
|
+
return this;
|
274
|
+
};
|
275
|
+
|
276
|
+
// destroy all children
|
277
|
+
result.destroy = function () {
|
278
|
+
this.front.destroy();
|
279
|
+
this.top.destroy();
|
280
|
+
this.side.destroy();
|
281
|
+
|
282
|
+
return null;
|
283
|
+
};
|
284
|
+
|
285
|
+
// Apply the Z index to the cuboid group
|
286
|
+
result.attr({ zIndex: -paths[3] });
|
287
|
+
|
288
|
+
return result;
|
289
|
+
};
|
290
|
+
|
291
|
+
/**
|
292
|
+
* Generates a cuboid
|
293
|
+
*/
|
294
|
+
Highcharts.SVGRenderer.prototype.cuboidPath = function (shapeArgs) {
|
295
|
+
var x = shapeArgs.x,
|
296
|
+
y = shapeArgs.y,
|
297
|
+
z = shapeArgs.z,
|
298
|
+
h = shapeArgs.height,
|
299
|
+
w = shapeArgs.width,
|
300
|
+
d = shapeArgs.depth,
|
301
|
+
chart = Highcharts.charts[this.chartIndex],
|
302
|
+
map = Highcharts.map;
|
303
|
+
|
304
|
+
// The 8 corners of the cube
|
305
|
+
var pArr = [
|
306
|
+
{ x: x, y: y, z: z },
|
307
|
+
{ x: x + w, y: y, z: z },
|
308
|
+
{ x: x + w, y: y + h, z: z },
|
309
|
+
{ x: x, y: y + h, z: z },
|
310
|
+
{ x: x, y: y + h, z: z + d },
|
311
|
+
{ x: x + w, y: y + h, z: z + d },
|
312
|
+
{ x: x + w, y: y, z: z + d },
|
313
|
+
{ x: x, y: y, z: z + d }
|
314
|
+
];
|
315
|
+
|
316
|
+
// apply perspective
|
317
|
+
pArr = perspective(pArr, chart, shapeArgs.insidePlotArea);
|
318
|
+
|
319
|
+
// helper method to decide which side is visible
|
320
|
+
function mapPath(i) {
|
321
|
+
return pArr[i];
|
322
|
+
}
|
323
|
+
var pickShape = function (path1, path2) {
|
324
|
+
var ret;
|
325
|
+
path1 = map(path1, mapPath);
|
326
|
+
path2 = map(path2, mapPath);
|
327
|
+
if (shapeArea(path1) < 0) {
|
328
|
+
ret = path1;
|
329
|
+
} else if (shapeArea(path2) < 0) {
|
330
|
+
ret = path2;
|
331
|
+
} else {
|
332
|
+
ret = [];
|
333
|
+
}
|
334
|
+
return ret;
|
335
|
+
};
|
336
|
+
|
337
|
+
// front or back
|
338
|
+
var front = [3, 2, 1, 0];
|
339
|
+
var back = [7, 6, 5, 4];
|
340
|
+
var path1 = pickShape(front, back);
|
341
|
+
|
342
|
+
// top or bottom
|
343
|
+
var top = [1, 6, 7, 0];
|
344
|
+
var bottom = [4, 5, 2, 3];
|
345
|
+
var path2 = pickShape(top, bottom);
|
346
|
+
|
347
|
+
// side
|
348
|
+
var right = [1, 2, 5, 6];
|
349
|
+
var left = [0, 7, 4, 3];
|
350
|
+
var path3 = pickShape(right, left);
|
351
|
+
|
352
|
+
return [this.toLinePath(path1, true), this.toLinePath(path2, true), this.toLinePath(path3, true), averageZ(path1), averageZ(path2), averageZ(path3)];
|
353
|
+
};
|
354
|
+
|
355
|
+
////// SECTORS //////
|
356
|
+
Highcharts.SVGRenderer.prototype.arc3d = function (attribs) {
|
357
|
+
|
358
|
+
var wrapper = this.g(),
|
359
|
+
renderer = wrapper.renderer,
|
360
|
+
customAttribs = ['x', 'y', 'r', 'innerR', 'start', 'end'];
|
361
|
+
|
362
|
+
/**
|
363
|
+
* Get custom attributes. Mutate the original object and return an object with only custom attr.
|
364
|
+
*/
|
365
|
+
function suckOutCustom(params) {
|
366
|
+
var hasCA = false,
|
367
|
+
ca = {};
|
368
|
+
for (var key in params) {
|
369
|
+
if (inArray(key, customAttribs) !== -1) {
|
370
|
+
ca[key] = params[key];
|
371
|
+
delete params[key];
|
372
|
+
hasCA = true;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
return hasCA ? ca : false;
|
376
|
+
}
|
377
|
+
|
378
|
+
attribs = merge(attribs);
|
379
|
+
|
380
|
+
attribs.alpha *= deg2rad;
|
381
|
+
attribs.beta *= deg2rad;
|
382
|
+
|
383
|
+
// Create the different sub sections of the shape
|
384
|
+
wrapper.top = renderer.path();
|
385
|
+
wrapper.side1 = renderer.path();
|
386
|
+
wrapper.side2 = renderer.path();
|
387
|
+
wrapper.inn = renderer.path();
|
388
|
+
wrapper.out = renderer.path();
|
389
|
+
|
390
|
+
/**
|
391
|
+
* Add all faces
|
392
|
+
*/
|
393
|
+
wrapper.onAdd = function () {
|
394
|
+
var parent = wrapper.parentGroup;
|
395
|
+
wrapper.top.add(wrapper);
|
396
|
+
wrapper.out.add(parent);
|
397
|
+
wrapper.inn.add(parent);
|
398
|
+
wrapper.side1.add(parent);
|
399
|
+
wrapper.side2.add(parent);
|
400
|
+
};
|
401
|
+
|
402
|
+
/**
|
403
|
+
* Compute the transformed paths and set them to the composite shapes
|
404
|
+
*/
|
405
|
+
wrapper.setPaths = function (attribs) {
|
406
|
+
|
407
|
+
var paths = wrapper.renderer.arc3dPath(attribs),
|
408
|
+
zIndex = paths.zTop * 100;
|
409
|
+
|
410
|
+
wrapper.attribs = attribs;
|
411
|
+
|
412
|
+
wrapper.top.attr({ d: paths.top, zIndex: paths.zTop });
|
413
|
+
wrapper.inn.attr({ d: paths.inn, zIndex: paths.zInn });
|
414
|
+
wrapper.out.attr({ d: paths.out, zIndex: paths.zOut });
|
415
|
+
wrapper.side1.attr({ d: paths.side1, zIndex: paths.zSide1 });
|
416
|
+
wrapper.side2.attr({ d: paths.side2, zIndex: paths.zSide2 });
|
417
|
+
|
418
|
+
|
419
|
+
// show all children
|
420
|
+
wrapper.zIndex = zIndex;
|
421
|
+
wrapper.attr({ zIndex: zIndex });
|
422
|
+
|
423
|
+
// Set the radial gradient center the first time
|
424
|
+
if (attribs.center) {
|
425
|
+
wrapper.top.setRadialReference(attribs.center);
|
426
|
+
delete attribs.center;
|
427
|
+
}
|
428
|
+
};
|
429
|
+
wrapper.setPaths(attribs);
|
430
|
+
|
431
|
+
// Apply the fill to the top and a darker shade to the sides
|
432
|
+
wrapper.fillSetter = function (value) {
|
433
|
+
var darker = Highcharts.Color(value).brighten(-0.1).get();
|
434
|
+
|
435
|
+
this.fill = value;
|
436
|
+
|
437
|
+
this.side1.attr({ fill: darker });
|
438
|
+
this.side2.attr({ fill: darker });
|
439
|
+
this.inn.attr({ fill: darker });
|
440
|
+
this.out.attr({ fill: darker });
|
441
|
+
this.top.attr({ fill: value });
|
442
|
+
return this;
|
443
|
+
};
|
444
|
+
|
445
|
+
// Apply the same value to all. These properties cascade down to the children
|
446
|
+
// when set to the composite arc3d.
|
447
|
+
each(['opacity', 'translateX', 'translateY', 'visibility'], function (setter) {
|
448
|
+
wrapper[setter + 'Setter'] = function (value, key) {
|
449
|
+
wrapper[key] = value;
|
450
|
+
each(['out', 'inn', 'side1', 'side2', 'top'], function (el) {
|
451
|
+
wrapper[el].attr(key, value);
|
452
|
+
});
|
453
|
+
};
|
454
|
+
});
|
455
|
+
|
456
|
+
/**
|
457
|
+
* Override attr to remove shape attributes and use those to set child paths
|
458
|
+
*/
|
459
|
+
wrap(wrapper, 'attr', function (proceed, params, val) {
|
460
|
+
var ca;
|
461
|
+
if (typeof params === 'object') {
|
462
|
+
ca = suckOutCustom(params);
|
463
|
+
if (ca) {
|
464
|
+
extend(wrapper.attribs, ca);
|
465
|
+
wrapper.setPaths(wrapper.attribs);
|
466
|
+
}
|
467
|
+
}
|
468
|
+
return proceed.call(this, params, val);
|
469
|
+
});
|
470
|
+
|
471
|
+
/**
|
472
|
+
* Override the animate function by sucking out custom parameters related to the shapes directly,
|
473
|
+
* and update the shapes from the animation step.
|
474
|
+
*/
|
475
|
+
wrap(wrapper, 'animate', function (proceed, params, animation, complete) {
|
476
|
+
var ca,
|
477
|
+
from = this.attribs,
|
478
|
+
to;
|
479
|
+
|
480
|
+
// Attribute-line properties connected to 3D. These shouldn't have been in the
|
481
|
+
// attribs collection in the first place.
|
482
|
+
delete params.center;
|
483
|
+
delete params.z;
|
484
|
+
delete params.depth;
|
485
|
+
delete params.alpha;
|
486
|
+
delete params.beta;
|
487
|
+
|
488
|
+
animation = pick(animation, this.renderer.globalAnimation);
|
489
|
+
|
490
|
+
if (animation) {
|
491
|
+
if (typeof animation !== 'object') {
|
492
|
+
animation = {};
|
493
|
+
}
|
494
|
+
|
495
|
+
params = merge(params); // Don't mutate the original object
|
496
|
+
ca = suckOutCustom(params);
|
497
|
+
|
498
|
+
if (ca) {
|
499
|
+
to = ca;
|
500
|
+
animation.step = function (a, fx) {
|
501
|
+
function interpolate(key) {
|
502
|
+
return from[key] + (pick(to[key], from[key]) - from[key]) * fx.pos;
|
503
|
+
}
|
504
|
+
fx.elem.setPaths(merge(from, {
|
505
|
+
x: interpolate('x'),
|
506
|
+
y: interpolate('y'),
|
507
|
+
r: interpolate('r'),
|
508
|
+
innerR: interpolate('innerR'),
|
509
|
+
start: interpolate('start'),
|
510
|
+
end: interpolate('end')
|
511
|
+
}));
|
512
|
+
};
|
513
|
+
}
|
514
|
+
}
|
515
|
+
return proceed.call(this, params, animation, complete);
|
516
|
+
});
|
517
|
+
|
518
|
+
// destroy all children
|
519
|
+
wrapper.destroy = function () {
|
520
|
+
this.top.destroy();
|
521
|
+
this.out.destroy();
|
522
|
+
this.inn.destroy();
|
523
|
+
this.side1.destroy();
|
524
|
+
this.side2.destroy();
|
525
|
+
|
526
|
+
Highcharts.SVGElement.prototype.destroy.call(this);
|
527
|
+
};
|
528
|
+
// hide all children
|
529
|
+
wrapper.hide = function () {
|
530
|
+
this.top.hide();
|
531
|
+
this.out.hide();
|
532
|
+
this.inn.hide();
|
533
|
+
this.side1.hide();
|
534
|
+
this.side2.hide();
|
535
|
+
};
|
536
|
+
wrapper.show = function () {
|
537
|
+
this.top.show();
|
538
|
+
this.out.show();
|
539
|
+
this.inn.show();
|
540
|
+
this.side1.show();
|
541
|
+
this.side2.show();
|
542
|
+
};
|
543
|
+
return wrapper;
|
544
|
+
};
|
545
|
+
|
546
|
+
/**
|
547
|
+
* Generate the paths required to draw a 3D arc
|
548
|
+
*/
|
549
|
+
Highcharts.SVGRenderer.prototype.arc3dPath = function (shapeArgs) {
|
550
|
+
var cx = shapeArgs.x, // x coordinate of the center
|
551
|
+
cy = shapeArgs.y, // y coordinate of the center
|
552
|
+
start = shapeArgs.start, // start angle
|
553
|
+
end = shapeArgs.end - 0.00001, // end angle
|
554
|
+
r = shapeArgs.r, // radius
|
555
|
+
ir = shapeArgs.innerR, // inner radius
|
556
|
+
d = shapeArgs.depth, // depth
|
557
|
+
alpha = shapeArgs.alpha, // alpha rotation of the chart
|
558
|
+
beta = shapeArgs.beta; // beta rotation of the chart
|
559
|
+
|
560
|
+
// Derived Variables
|
561
|
+
var cs = cos(start), // cosinus of the start angle
|
562
|
+
ss = sin(start), // sinus of the start angle
|
563
|
+
ce = cos(end), // cosinus of the end angle
|
564
|
+
se = sin(end), // sinus of the end angle
|
565
|
+
rx = r * cos(beta), // x-radius
|
566
|
+
ry = r * cos(alpha), // y-radius
|
567
|
+
irx = ir * cos(beta), // x-radius (inner)
|
568
|
+
iry = ir * cos(alpha), // y-radius (inner)
|
569
|
+
dx = d * sin(beta), // distance between top and bottom in x
|
570
|
+
dy = d * sin(alpha); // distance between top and bottom in y
|
571
|
+
|
572
|
+
// TOP
|
573
|
+
var top = ['M', cx + (rx * cs), cy + (ry * ss)];
|
574
|
+
top = top.concat(curveTo(cx, cy, rx, ry, start, end, 0, 0));
|
575
|
+
top = top.concat([
|
576
|
+
'L', cx + (irx * ce), cy + (iry * se)
|
577
|
+
]);
|
578
|
+
top = top.concat(curveTo(cx, cy, irx, iry, end, start, 0, 0));
|
579
|
+
top = top.concat(['Z']);
|
580
|
+
// OUTSIDE
|
581
|
+
var b = (beta > 0 ? PI / 2 : 0),
|
582
|
+
a = (alpha > 0 ? 0 : PI / 2);
|
583
|
+
|
584
|
+
var start2 = start > -b ? start : (end > -b ? -b : start),
|
585
|
+
end2 = end < PI - a ? end : (start < PI - a ? PI - a : end),
|
586
|
+
midEnd = 2 * PI - a;
|
587
|
+
|
588
|
+
// When slice goes over bottom middle, need to add both, left and right outer side.
|
589
|
+
// Additionally, when we cross right hand edge, create sharp edge. Outer shape/wall:
|
590
|
+
//
|
591
|
+
// -------
|
592
|
+
// / ^ \
|
593
|
+
// 4) / / \ \ 1)
|
594
|
+
// / / \ \
|
595
|
+
// / / \ \
|
596
|
+
// (c)=> ==== ==== <=(d)
|
597
|
+
// \ \ / /
|
598
|
+
// \ \<=(a)/ /
|
599
|
+
// \ \ / / <=(b)
|
600
|
+
// 3) \ v / 2)
|
601
|
+
// -------
|
602
|
+
//
|
603
|
+
// (a) - inner side
|
604
|
+
// (b) - outer side
|
605
|
+
// (c) - left edge (sharp)
|
606
|
+
// (d) - right edge (sharp)
|
607
|
+
// 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
|
608
|
+
|
609
|
+
var out = ['M', cx + (rx * cos(start2)), cy + (ry * sin(start2))];
|
610
|
+
out = out.concat(curveTo(cx, cy, rx, ry, start2, end2, 0, 0));
|
611
|
+
|
612
|
+
if (end > midEnd && start < midEnd) { // When shape is wide, it can cross both, (c) and (d) edges, when using startAngle
|
613
|
+
// Go to outer side
|
614
|
+
out = out.concat([
|
615
|
+
'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy
|
616
|
+
]);
|
617
|
+
// Curve to the right edge of the slice (d)
|
618
|
+
out = out.concat(curveTo(cx, cy, rx, ry, end2, midEnd, dx, dy));
|
619
|
+
// Go to the inner side
|
620
|
+
out = out.concat([
|
621
|
+
'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd))
|
622
|
+
]);
|
623
|
+
// Curve to the true end of the slice
|
624
|
+
out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end, 0, 0));
|
625
|
+
// Go to the outer side
|
626
|
+
out = out.concat([
|
627
|
+
'L', cx + (rx * cos(end)) + dx, cy + (ry * sin(end)) + dy
|
628
|
+
]);
|
629
|
+
// Go back to middle (d)
|
630
|
+
out = out.concat(curveTo(cx, cy, rx, ry, end, midEnd, dx, dy));
|
631
|
+
out = out.concat([
|
632
|
+
'L', cx + (rx * cos(midEnd)), cy + (ry * sin(midEnd))
|
633
|
+
]);
|
634
|
+
// Go back to the left edge
|
635
|
+
out = out.concat(curveTo(cx, cy, rx, ry, midEnd, end2, 0, 0));
|
636
|
+
} else if (end > PI - a && start < PI - a) { // But shape can cross also only (c) edge:
|
637
|
+
// Go to outer side
|
638
|
+
out = out.concat([
|
639
|
+
'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy
|
640
|
+
]);
|
641
|
+
// Curve to the true end of the slice
|
642
|
+
out = out.concat(curveTo(cx, cy, rx, ry, end2, end, dx, dy));
|
643
|
+
// Go to the inner side
|
644
|
+
out = out.concat([
|
645
|
+
'L', cx + (rx * cos(end)), cy + (ry * sin(end))
|
646
|
+
]);
|
647
|
+
// Go back to the artifical end2
|
648
|
+
out = out.concat(curveTo(cx, cy, rx, ry, end, end2, 0, 0));
|
649
|
+
}
|
650
|
+
|
651
|
+
out = out.concat([
|
652
|
+
'L', cx + (rx * cos(end2)) + dx, cy + (ry * sin(end2)) + dy
|
653
|
+
]);
|
654
|
+
out = out.concat(curveTo(cx, cy, rx, ry, end2, start2, dx, dy));
|
655
|
+
out = out.concat(['Z']);
|
656
|
+
|
657
|
+
// INSIDE
|
658
|
+
var inn = ['M', cx + (irx * cs), cy + (iry * ss)];
|
659
|
+
inn = inn.concat(curveTo(cx, cy, irx, iry, start, end, 0, 0));
|
660
|
+
inn = inn.concat([
|
661
|
+
'L', cx + (irx * cos(end)) + dx, cy + (iry * sin(end)) + dy
|
662
|
+
]);
|
663
|
+
inn = inn.concat(curveTo(cx, cy, irx, iry, end, start, dx, dy));
|
664
|
+
inn = inn.concat(['Z']);
|
665
|
+
|
666
|
+
// SIDES
|
667
|
+
var side1 = [
|
668
|
+
'M', cx + (rx * cs), cy + (ry * ss),
|
669
|
+
'L', cx + (rx * cs) + dx, cy + (ry * ss) + dy,
|
670
|
+
'L', cx + (irx * cs) + dx, cy + (iry * ss) + dy,
|
671
|
+
'L', cx + (irx * cs), cy + (iry * ss),
|
672
|
+
'Z'
|
673
|
+
];
|
674
|
+
var side2 = [
|
675
|
+
'M', cx + (rx * ce), cy + (ry * se),
|
676
|
+
'L', cx + (rx * ce) + dx, cy + (ry * se) + dy,
|
677
|
+
'L', cx + (irx * ce) + dx, cy + (iry * se) + dy,
|
678
|
+
'L', cx + (irx * ce), cy + (iry * se),
|
679
|
+
'Z'
|
680
|
+
];
|
681
|
+
|
682
|
+
// correction for changed position of vanishing point caused by alpha and beta rotations
|
683
|
+
var angleCorr = Math.atan2(dy, -dx),
|
684
|
+
angleEnd = Math.abs(end + angleCorr),
|
685
|
+
angleStart = Math.abs(start + angleCorr),
|
686
|
+
angleMid = Math.abs((start + end) / 2 + angleCorr);
|
687
|
+
|
688
|
+
// set to 0-PI range
|
689
|
+
function toZeroPIRange(angle) {
|
690
|
+
angle = angle % (2 * PI);
|
691
|
+
if (angle > PI) {
|
692
|
+
angle = 2 * PI - angle;
|
693
|
+
}
|
694
|
+
return angle;
|
695
|
+
}
|
696
|
+
angleEnd = toZeroPIRange(angleEnd);
|
697
|
+
angleStart = toZeroPIRange(angleStart);
|
698
|
+
angleMid = toZeroPIRange(angleMid);
|
699
|
+
|
700
|
+
// *1e5 is to compensate pInt in zIndexSetter
|
701
|
+
var incPrecision = 1e5,
|
702
|
+
a1 = angleMid * incPrecision,
|
703
|
+
a2 = angleStart * incPrecision,
|
704
|
+
a3 = angleEnd * incPrecision;
|
705
|
+
|
706
|
+
return {
|
707
|
+
top: top,
|
708
|
+
zTop: PI * incPrecision + 1, // max angle is PI, so this is allways higher
|
709
|
+
out: out,
|
710
|
+
zOut: Math.max(a1, a2, a3),
|
711
|
+
inn: inn,
|
712
|
+
zInn: Math.max(a1, a2, a3),
|
713
|
+
side1: side1,
|
714
|
+
zSide1: a3 * 0.99, // to keep below zOut and zInn in case of same values
|
715
|
+
side2: side2,
|
716
|
+
zSide2: a2 * 0.99
|
717
|
+
};
|
718
|
+
};
|
719
|
+
/***
|
720
|
+
EXTENSION FOR 3D CHARTS
|
721
|
+
***/
|
722
|
+
// Shorthand to check the is3d flag
|
723
|
+
Highcharts.Chart.prototype.is3d = function () {
|
724
|
+
return this.options.chart.options3d && this.options.chart.options3d.enabled; // #4280
|
725
|
+
};
|
726
|
+
|
727
|
+
Highcharts.wrap(Highcharts.Chart.prototype, 'isInsidePlot', function (proceed) {
|
728
|
+
return this.is3d() || proceed.apply(this, [].slice.call(arguments, 1));
|
729
|
+
});
|
730
|
+
|
731
|
+
var defaultChartOptions = Highcharts.getOptions();
|
732
|
+
defaultChartOptions.chart.options3d = {
|
733
|
+
enabled: false,
|
734
|
+
alpha: 0,
|
735
|
+
beta: 0,
|
736
|
+
depth: 100,
|
737
|
+
viewDistance: 25,
|
738
|
+
frame: {
|
739
|
+
bottom: { size: 1, color: 'rgba(255,255,255,0)' },
|
740
|
+
side: { size: 1, color: 'rgba(255,255,255,0)' },
|
741
|
+
back: { size: 1, color: 'rgba(255,255,255,0)' }
|
742
|
+
}
|
743
|
+
};
|
744
|
+
|
745
|
+
Highcharts.wrap(Highcharts.Chart.prototype, 'init', function (proceed) {
|
746
|
+
var args = [].slice.call(arguments, 1),
|
747
|
+
plotOptions,
|
748
|
+
pieOptions;
|
749
|
+
|
750
|
+
if (args[0].chart.options3d && args[0].chart.options3d.enabled) {
|
751
|
+
// Normalize alpha and beta to (-360, 360) range
|
752
|
+
args[0].chart.options3d.alpha = (args[0].chart.options3d.alpha || 0) % 360;
|
753
|
+
args[0].chart.options3d.beta = (args[0].chart.options3d.beta || 0) % 360;
|
754
|
+
|
755
|
+
plotOptions = args[0].plotOptions || {};
|
756
|
+
pieOptions = plotOptions.pie || {};
|
757
|
+
|
758
|
+
pieOptions.borderColor = Highcharts.pick(pieOptions.borderColor, undefined);
|
759
|
+
}
|
760
|
+
proceed.apply(this, args);
|
761
|
+
});
|
762
|
+
|
763
|
+
Highcharts.wrap(Highcharts.Chart.prototype, 'setChartSize', function (proceed) {
|
764
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
765
|
+
|
766
|
+
if (this.is3d()) {
|
767
|
+
var inverted = this.inverted,
|
768
|
+
clipBox = this.clipBox,
|
769
|
+
margin = this.margin,
|
770
|
+
x = inverted ? 'y' : 'x',
|
771
|
+
y = inverted ? 'x' : 'y',
|
772
|
+
w = inverted ? 'height' : 'width',
|
773
|
+
h = inverted ? 'width' : 'height';
|
774
|
+
|
775
|
+
clipBox[x] = -(margin[3] || 0);
|
776
|
+
clipBox[y] = -(margin[0] || 0);
|
777
|
+
clipBox[w] = this.chartWidth + (margin[3] || 0) + (margin[1] || 0);
|
778
|
+
clipBox[h] = this.chartHeight + (margin[0] || 0) + (margin[2] || 0);
|
779
|
+
}
|
780
|
+
});
|
781
|
+
|
782
|
+
Highcharts.wrap(Highcharts.Chart.prototype, 'redraw', function (proceed) {
|
783
|
+
if (this.is3d()) {
|
784
|
+
// Set to force a redraw of all elements
|
785
|
+
this.isDirtyBox = true;
|
786
|
+
}
|
787
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
788
|
+
});
|
789
|
+
|
790
|
+
// Draw the series in the reverse order (#3803, #3917)
|
791
|
+
Highcharts.wrap(Highcharts.Chart.prototype, 'renderSeries', function (proceed) {
|
792
|
+
var series,
|
793
|
+
i = this.series.length;
|
794
|
+
|
795
|
+
if (this.is3d()) {
|
796
|
+
while (i--) {
|
797
|
+
series = this.series[i];
|
798
|
+
series.translate();
|
799
|
+
series.render();
|
800
|
+
}
|
801
|
+
} else {
|
802
|
+
proceed.call(this);
|
803
|
+
}
|
804
|
+
});
|
805
|
+
|
806
|
+
Highcharts.Chart.prototype.retrieveStacks = function (stacking) {
|
807
|
+
var series = this.series,
|
808
|
+
stacks = {},
|
809
|
+
stackNumber,
|
810
|
+
i = 1;
|
811
|
+
|
812
|
+
Highcharts.each(this.series, function (s) {
|
813
|
+
stackNumber = pick(s.options.stack, (stacking ? 0 : series.length - 1 - s.index)); // #3841, #4532
|
814
|
+
if (!stacks[stackNumber]) {
|
815
|
+
stacks[stackNumber] = { series: [s], position: i };
|
816
|
+
i++;
|
817
|
+
} else {
|
818
|
+
stacks[stackNumber].series.push(s);
|
819
|
+
}
|
820
|
+
});
|
821
|
+
|
822
|
+
stacks.totalStacks = i + 1;
|
823
|
+
return stacks;
|
824
|
+
};
|
825
|
+
|
826
|
+
/***
|
827
|
+
EXTENSION TO THE AXIS
|
828
|
+
***/
|
829
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'setOptions', function (proceed, userOptions) {
|
830
|
+
var options;
|
831
|
+
proceed.call(this, userOptions);
|
832
|
+
if (this.chart.is3d()) {
|
833
|
+
options = this.options;
|
834
|
+
options.tickWidth = Highcharts.pick(options.tickWidth, 0);
|
835
|
+
options.gridLineWidth = Highcharts.pick(options.gridLineWidth, 1);
|
836
|
+
}
|
837
|
+
});
|
838
|
+
|
839
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'render', function (proceed) {
|
840
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
841
|
+
|
842
|
+
// Do not do this if the chart is not 3D
|
843
|
+
if (!this.chart.is3d()) {
|
844
|
+
return;
|
845
|
+
}
|
846
|
+
|
847
|
+
var chart = this.chart,
|
848
|
+
renderer = chart.renderer,
|
849
|
+
options3d = chart.options.chart.options3d,
|
850
|
+
frame = options3d.frame,
|
851
|
+
fbottom = frame.bottom,
|
852
|
+
fback = frame.back,
|
853
|
+
fside = frame.side,
|
854
|
+
depth = options3d.depth,
|
855
|
+
height = this.height,
|
856
|
+
width = this.width,
|
857
|
+
left = this.left,
|
858
|
+
top = this.top;
|
859
|
+
|
860
|
+
if (this.isZAxis) {
|
861
|
+
return;
|
862
|
+
}
|
863
|
+
if (this.horiz) {
|
864
|
+
var bottomShape = {
|
865
|
+
x: left,
|
866
|
+
y: top + (chart.xAxis[0].opposite ? -fbottom.size : height),
|
867
|
+
z: 0,
|
868
|
+
width: width,
|
869
|
+
height: fbottom.size,
|
870
|
+
depth: depth,
|
871
|
+
insidePlotArea: false
|
872
|
+
};
|
873
|
+
if (!this.bottomFrame) {
|
874
|
+
this.bottomFrame = renderer.cuboid(bottomShape).attr({
|
875
|
+
fill: fbottom.color,
|
876
|
+
zIndex: (chart.yAxis[0].reversed && options3d.alpha > 0 ? 4 : -1)
|
877
|
+
})
|
878
|
+
.css({
|
879
|
+
stroke: fbottom.color
|
880
|
+
}).add();
|
881
|
+
} else {
|
882
|
+
this.bottomFrame.animate(bottomShape);
|
883
|
+
}
|
884
|
+
} else {
|
885
|
+
// BACK
|
886
|
+
var backShape = {
|
887
|
+
x: left + (chart.yAxis[0].opposite ? 0 : -fside.size),
|
888
|
+
y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
|
889
|
+
z: depth,
|
890
|
+
width: width + fside.size,
|
891
|
+
height: height + fbottom.size,
|
892
|
+
depth: fback.size,
|
893
|
+
insidePlotArea: false
|
894
|
+
};
|
895
|
+
if (!this.backFrame) {
|
896
|
+
this.backFrame = renderer.cuboid(backShape).attr({
|
897
|
+
fill: fback.color,
|
898
|
+
zIndex: -3
|
899
|
+
}).css({
|
900
|
+
stroke: fback.color
|
901
|
+
}).add();
|
902
|
+
} else {
|
903
|
+
this.backFrame.animate(backShape);
|
904
|
+
}
|
905
|
+
var sideShape = {
|
906
|
+
x: left + (chart.yAxis[0].opposite ? width : -fside.size),
|
907
|
+
y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
|
908
|
+
z: 0,
|
909
|
+
width: fside.size,
|
910
|
+
height: height + fbottom.size,
|
911
|
+
depth: depth,
|
912
|
+
insidePlotArea: false
|
913
|
+
};
|
914
|
+
if (!this.sideFrame) {
|
915
|
+
this.sideFrame = renderer.cuboid(sideShape).attr({
|
916
|
+
fill: fside.color,
|
917
|
+
zIndex: -2
|
918
|
+
}).css({
|
919
|
+
stroke: fside.color
|
920
|
+
}).add();
|
921
|
+
} else {
|
922
|
+
this.sideFrame.animate(sideShape);
|
923
|
+
}
|
924
|
+
}
|
925
|
+
});
|
926
|
+
|
927
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'getPlotLinePath', function (proceed) {
|
928
|
+
var path = proceed.apply(this, [].slice.call(arguments, 1));
|
929
|
+
|
930
|
+
// Do not do this if the chart is not 3D
|
931
|
+
if (!this.chart.is3d()) {
|
932
|
+
return path;
|
933
|
+
}
|
934
|
+
|
935
|
+
if (path === null) {
|
936
|
+
return path;
|
937
|
+
}
|
938
|
+
|
939
|
+
var chart = this.chart,
|
940
|
+
options3d = chart.options.chart.options3d,
|
941
|
+
d = this.isZAxis ? chart.plotWidth : options3d.depth,
|
942
|
+
opposite = this.opposite;
|
943
|
+
if (this.horiz) {
|
944
|
+
opposite = !opposite;
|
945
|
+
}
|
946
|
+
var pArr = [
|
947
|
+
this.swapZ({ x: path[1], y: path[2], z: (opposite ? d : 0) }),
|
948
|
+
this.swapZ({ x: path[1], y: path[2], z: d }),
|
949
|
+
this.swapZ({ x: path[4], y: path[5], z: d }),
|
950
|
+
this.swapZ({ x: path[4], y: path[5], z: (opposite ? 0 : d) })
|
951
|
+
];
|
952
|
+
|
953
|
+
pArr = perspective(pArr, this.chart, false);
|
954
|
+
path = this.chart.renderer.toLinePath(pArr, false);
|
955
|
+
|
956
|
+
return path;
|
957
|
+
});
|
958
|
+
|
959
|
+
// Do not draw axislines in 3D
|
960
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'getLinePath', function (proceed) {
|
961
|
+
return this.chart.is3d() ? [] : proceed.apply(this, [].slice.call(arguments, 1));
|
962
|
+
});
|
963
|
+
|
964
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'getPlotBandPath', function (proceed) {
|
965
|
+
// Do not do this if the chart is not 3D
|
966
|
+
if (!this.chart.is3d()) {
|
967
|
+
return proceed.apply(this, [].slice.call(arguments, 1));
|
968
|
+
}
|
969
|
+
|
970
|
+
var args = arguments,
|
971
|
+
from = args[1],
|
972
|
+
to = args[2],
|
973
|
+
toPath = this.getPlotLinePath(to),
|
974
|
+
path = this.getPlotLinePath(from);
|
975
|
+
|
976
|
+
if (path && toPath) {
|
977
|
+
path.push(
|
978
|
+
'L',
|
979
|
+
toPath[10], // These two do not exist in the regular getPlotLine
|
980
|
+
toPath[11], // ---- # 3005
|
981
|
+
'L',
|
982
|
+
toPath[7],
|
983
|
+
toPath[8],
|
984
|
+
'L',
|
985
|
+
toPath[4],
|
986
|
+
toPath[5],
|
987
|
+
'L',
|
988
|
+
toPath[1],
|
989
|
+
toPath[2]
|
990
|
+
);
|
991
|
+
} else { // outside the axis area
|
992
|
+
path = null;
|
993
|
+
}
|
994
|
+
|
995
|
+
return path;
|
996
|
+
});
|
997
|
+
|
998
|
+
/***
|
999
|
+
EXTENSION TO THE TICKS
|
1000
|
+
***/
|
1001
|
+
|
1002
|
+
Highcharts.wrap(Highcharts.Tick.prototype, 'getMarkPath', function (proceed) {
|
1003
|
+
var path = proceed.apply(this, [].slice.call(arguments, 1));
|
1004
|
+
|
1005
|
+
// Do not do this if the chart is not 3D
|
1006
|
+
if (!this.axis.chart.is3d()) {
|
1007
|
+
return path;
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
var pArr = [
|
1011
|
+
this.axis.swapZ({ x: path[1], y: path[2], z: 0 }),
|
1012
|
+
this.axis.swapZ({ x: path[4], y: path[5], z: 0 })
|
1013
|
+
];
|
1014
|
+
|
1015
|
+
pArr = perspective(pArr, this.axis.chart, false);
|
1016
|
+
path = [
|
1017
|
+
'M', pArr[0].x, pArr[0].y,
|
1018
|
+
'L', pArr[1].x, pArr[1].y
|
1019
|
+
];
|
1020
|
+
return path;
|
1021
|
+
});
|
1022
|
+
|
1023
|
+
Highcharts.wrap(Highcharts.Tick.prototype, 'getLabelPosition', function (proceed) {
|
1024
|
+
var pos = proceed.apply(this, [].slice.call(arguments, 1));
|
1025
|
+
|
1026
|
+
// Do not do this if the chart is not 3D
|
1027
|
+
if (!this.axis.chart.is3d()) {
|
1028
|
+
return pos;
|
1029
|
+
}
|
1030
|
+
|
1031
|
+
var newPos = perspective([this.axis.swapZ({ x: pos.x, y: pos.y, z: 0 })], this.axis.chart, false)[0];
|
1032
|
+
newPos.x = newPos.x - (!this.axis.horiz && this.axis.opposite ? this.axis.transA : 0); //#3788
|
1033
|
+
newPos.old = pos;
|
1034
|
+
return newPos;
|
1035
|
+
});
|
1036
|
+
|
1037
|
+
Highcharts.wrap(Highcharts.Tick.prototype, 'handleOverflow', function (proceed, xy) {
|
1038
|
+
if (this.axis.chart.is3d()) {
|
1039
|
+
xy = xy.old;
|
1040
|
+
}
|
1041
|
+
return proceed.call(this, xy);
|
1042
|
+
});
|
1043
|
+
|
1044
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'getTitlePosition', function (proceed) {
|
1045
|
+
var is3d = this.chart.is3d(),
|
1046
|
+
pos,
|
1047
|
+
axisTitleMargin;
|
1048
|
+
|
1049
|
+
// Pull out the axis title margin, that is not subject to the perspective
|
1050
|
+
if (is3d) {
|
1051
|
+
axisTitleMargin = this.axisTitleMargin;
|
1052
|
+
this.axisTitleMargin = 0;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
pos = proceed.apply(this, [].slice.call(arguments, 1));
|
1056
|
+
|
1057
|
+
if (is3d) {
|
1058
|
+
pos = perspective([this.swapZ({ x: pos.x, y: pos.y, z: 0 })], this.chart, false)[0];
|
1059
|
+
|
1060
|
+
// Re-apply the axis title margin outside the perspective
|
1061
|
+
pos[this.horiz ? 'y' : 'x'] += (this.horiz ? 1 : -1) * // horizontal axis reverses the margin ...
|
1062
|
+
(this.opposite ? -1 : 1) * // ... so does opposite axes
|
1063
|
+
axisTitleMargin;
|
1064
|
+
this.axisTitleMargin = axisTitleMargin;
|
1065
|
+
}
|
1066
|
+
return pos;
|
1067
|
+
});
|
1068
|
+
|
1069
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'drawCrosshair', function (proceed) {
|
1070
|
+
var args = arguments;
|
1071
|
+
if (this.chart.is3d()) {
|
1072
|
+
if (args[2]) {
|
1073
|
+
args[2] = {
|
1074
|
+
plotX: args[2].plotXold || args[2].plotX,
|
1075
|
+
plotY: args[2].plotYold || args[2].plotY
|
1076
|
+
};
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
proceed.apply(this, [].slice.call(args, 1));
|
1080
|
+
});
|
1081
|
+
|
1082
|
+
/***
|
1083
|
+
Z-AXIS
|
1084
|
+
***/
|
1085
|
+
|
1086
|
+
Highcharts.Axis.prototype.swapZ = function (p, insidePlotArea) {
|
1087
|
+
if (this.isZAxis) {
|
1088
|
+
var plotLeft = insidePlotArea ? 0 : this.chart.plotLeft;
|
1089
|
+
var chart = this.chart;
|
1090
|
+
return {
|
1091
|
+
x: plotLeft + (chart.yAxis[0].opposite ? p.z : chart.xAxis[0].width - p.z),
|
1092
|
+
y: p.y,
|
1093
|
+
z: p.x - plotLeft
|
1094
|
+
};
|
1095
|
+
}
|
1096
|
+
return p;
|
1097
|
+
};
|
1098
|
+
|
1099
|
+
var ZAxis = Highcharts.ZAxis = function () {
|
1100
|
+
this.isZAxis = true;
|
1101
|
+
this.init.apply(this, arguments);
|
1102
|
+
};
|
1103
|
+
Highcharts.extend(ZAxis.prototype, Highcharts.Axis.prototype);
|
1104
|
+
Highcharts.extend(ZAxis.prototype, {
|
1105
|
+
setOptions: function (userOptions) {
|
1106
|
+
userOptions = Highcharts.merge({
|
1107
|
+
offset: 0,
|
1108
|
+
lineWidth: 0
|
1109
|
+
}, userOptions);
|
1110
|
+
Highcharts.Axis.prototype.setOptions.call(this, userOptions);
|
1111
|
+
this.coll = 'zAxis';
|
1112
|
+
},
|
1113
|
+
setAxisSize: function () {
|
1114
|
+
Highcharts.Axis.prototype.setAxisSize.call(this);
|
1115
|
+
this.width = this.len = this.chart.options.chart.options3d.depth;
|
1116
|
+
this.right = this.chart.chartWidth - this.width - this.left;
|
1117
|
+
},
|
1118
|
+
getSeriesExtremes: function () {
|
1119
|
+
var axis = this,
|
1120
|
+
chart = axis.chart;
|
1121
|
+
|
1122
|
+
axis.hasVisibleSeries = false;
|
1123
|
+
|
1124
|
+
// Reset properties in case we're redrawing (#3353)
|
1125
|
+
axis.dataMin = axis.dataMax = axis.ignoreMinPadding = axis.ignoreMaxPadding = null;
|
1126
|
+
|
1127
|
+
if (axis.buildStacks) {
|
1128
|
+
axis.buildStacks();
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
// loop through this axis' series
|
1132
|
+
Highcharts.each(axis.series, function (series) {
|
1133
|
+
|
1134
|
+
if (series.visible || !chart.options.chart.ignoreHiddenSeries) {
|
1135
|
+
|
1136
|
+
var seriesOptions = series.options,
|
1137
|
+
zData,
|
1138
|
+
threshold = seriesOptions.threshold;
|
1139
|
+
|
1140
|
+
axis.hasVisibleSeries = true;
|
1141
|
+
|
1142
|
+
// Validate threshold in logarithmic axes
|
1143
|
+
if (axis.isLog && threshold <= 0) {
|
1144
|
+
threshold = null;
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
zData = series.zData;
|
1148
|
+
if (zData.length) {
|
1149
|
+
axis.dataMin = Math.min(pick(axis.dataMin, zData[0]), Math.min.apply(null, zData));
|
1150
|
+
axis.dataMax = Math.max(pick(axis.dataMax, zData[0]), Math.max.apply(null, zData));
|
1151
|
+
}
|
1152
|
+
}
|
1153
|
+
});
|
1154
|
+
}
|
1155
|
+
});
|
1156
|
+
|
1157
|
+
|
1158
|
+
/**
|
1159
|
+
* Extend the chart getAxes method to also get the color axis
|
1160
|
+
*/
|
1161
|
+
Highcharts.wrap(Highcharts.Chart.prototype, 'getAxes', function (proceed) {
|
1162
|
+
var chart = this,
|
1163
|
+
options = this.options,
|
1164
|
+
zAxisOptions = options.zAxis = Highcharts.splat(options.zAxis || {});
|
1165
|
+
|
1166
|
+
proceed.call(this);
|
1167
|
+
|
1168
|
+
if (!chart.is3d()) {
|
1169
|
+
return;
|
1170
|
+
}
|
1171
|
+
this.zAxis = [];
|
1172
|
+
Highcharts.each(zAxisOptions, function (axisOptions, i) {
|
1173
|
+
axisOptions.index = i;
|
1174
|
+
axisOptions.isX = true; //Z-Axis is shown horizontally, so it's kind of a X-Axis
|
1175
|
+
var zAxis = new ZAxis(chart, axisOptions);
|
1176
|
+
zAxis.setScale();
|
1177
|
+
});
|
1178
|
+
});
|
1179
|
+
/***
|
1180
|
+
EXTENSION FOR 3D COLUMNS
|
1181
|
+
***/
|
1182
|
+
Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'translate', function (proceed) {
|
1183
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1184
|
+
|
1185
|
+
// Do not do this if the chart is not 3D
|
1186
|
+
if (!this.chart.is3d()) {
|
1187
|
+
return;
|
1188
|
+
}
|
1189
|
+
|
1190
|
+
var series = this,
|
1191
|
+
chart = series.chart,
|
1192
|
+
seriesOptions = series.options,
|
1193
|
+
depth = seriesOptions.depth || 25;
|
1194
|
+
|
1195
|
+
var stack = seriesOptions.stacking ? (seriesOptions.stack || 0) : series._i;
|
1196
|
+
var z = stack * (depth + (seriesOptions.groupZPadding || 1));
|
1197
|
+
|
1198
|
+
if (seriesOptions.grouping !== false) {
|
1199
|
+
z = 0;
|
1200
|
+
}
|
1201
|
+
|
1202
|
+
z += (seriesOptions.groupZPadding || 1);
|
1203
|
+
|
1204
|
+
Highcharts.each(series.data, function (point) {
|
1205
|
+
if (point.y !== null) {
|
1206
|
+
var shapeArgs = point.shapeArgs,
|
1207
|
+
tooltipPos = point.tooltipPos;
|
1208
|
+
|
1209
|
+
point.shapeType = 'cuboid';
|
1210
|
+
shapeArgs.z = z;
|
1211
|
+
shapeArgs.depth = depth;
|
1212
|
+
shapeArgs.insidePlotArea = true;
|
1213
|
+
|
1214
|
+
// Translate the tooltip position in 3d space
|
1215
|
+
tooltipPos = perspective([{ x: tooltipPos[0], y: tooltipPos[1], z: z }], chart, false)[0];
|
1216
|
+
point.tooltipPos = [tooltipPos.x, tooltipPos.y];
|
1217
|
+
}
|
1218
|
+
});
|
1219
|
+
// store for later use #4067
|
1220
|
+
series.z = z;
|
1221
|
+
});
|
1222
|
+
|
1223
|
+
Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'animate', function (proceed) {
|
1224
|
+
if (!this.chart.is3d()) {
|
1225
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1226
|
+
} else {
|
1227
|
+
var args = arguments,
|
1228
|
+
init = args[1],
|
1229
|
+
yAxis = this.yAxis,
|
1230
|
+
series = this,
|
1231
|
+
reversed = this.yAxis.reversed;
|
1232
|
+
|
1233
|
+
if (Highcharts.svg) { // VML is too slow anyway
|
1234
|
+
if (init) {
|
1235
|
+
Highcharts.each(series.data, function (point) {
|
1236
|
+
if (point.y !== null) {
|
1237
|
+
point.height = point.shapeArgs.height;
|
1238
|
+
point.shapey = point.shapeArgs.y; //#2968
|
1239
|
+
point.shapeArgs.height = 1;
|
1240
|
+
if (!reversed) {
|
1241
|
+
if (point.stackY) {
|
1242
|
+
point.shapeArgs.y = point.plotY + yAxis.translate(point.stackY);
|
1243
|
+
} else {
|
1244
|
+
point.shapeArgs.y = point.plotY + (point.negative ? -point.height : point.height);
|
1245
|
+
}
|
1246
|
+
}
|
1247
|
+
}
|
1248
|
+
});
|
1249
|
+
|
1250
|
+
} else { // run the animation
|
1251
|
+
Highcharts.each(series.data, function (point) {
|
1252
|
+
if (point.y !== null) {
|
1253
|
+
point.shapeArgs.height = point.height;
|
1254
|
+
point.shapeArgs.y = point.shapey; //#2968
|
1255
|
+
// null value do not have a graphic
|
1256
|
+
if (point.graphic) {
|
1257
|
+
point.graphic.animate(point.shapeArgs, series.options.animation);
|
1258
|
+
}
|
1259
|
+
}
|
1260
|
+
});
|
1261
|
+
|
1262
|
+
// redraw datalabels to the correct position
|
1263
|
+
this.drawDataLabels();
|
1264
|
+
|
1265
|
+
// delete this function to allow it only once
|
1266
|
+
series.animate = null;
|
1267
|
+
}
|
1268
|
+
}
|
1269
|
+
}
|
1270
|
+
});
|
1271
|
+
|
1272
|
+
Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'init', function (proceed) {
|
1273
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1274
|
+
|
1275
|
+
if (this.chart.is3d()) {
|
1276
|
+
var seriesOptions = this.options,
|
1277
|
+
grouping = seriesOptions.grouping,
|
1278
|
+
stacking = seriesOptions.stacking,
|
1279
|
+
reversedStacks = pick(this.yAxis.options.reversedStacks, true),
|
1280
|
+
z = 0;
|
1281
|
+
|
1282
|
+
if (!(grouping !== undefined && !grouping)) {
|
1283
|
+
var stacks = this.chart.retrieveStacks(stacking),
|
1284
|
+
stack = seriesOptions.stack || 0,
|
1285
|
+
i; // position within the stack
|
1286
|
+
for (i = 0; i < stacks[stack].series.length; i++) {
|
1287
|
+
if (stacks[stack].series[i] === this) {
|
1288
|
+
break;
|
1289
|
+
}
|
1290
|
+
}
|
1291
|
+
z = (10 * (stacks.totalStacks - stacks[stack].position)) + (reversedStacks ? i : -i); // #4369
|
1292
|
+
|
1293
|
+
// In case when axis is reversed, columns are also reversed inside the group (#3737)
|
1294
|
+
if (!this.xAxis.reversed) {
|
1295
|
+
z = (stacks.totalStacks * 10) - z;
|
1296
|
+
}
|
1297
|
+
}
|
1298
|
+
|
1299
|
+
seriesOptions.zIndex = z;
|
1300
|
+
}
|
1301
|
+
});
|
1302
|
+
function draw3DPoints(proceed) {
|
1303
|
+
// Do not do this if the chart is not 3D
|
1304
|
+
if (this.chart.is3d()) {
|
1305
|
+
var grouping = this.chart.options.plotOptions.column.grouping;
|
1306
|
+
if (grouping !== undefined && !grouping && this.group.zIndex !== undefined && !this.zIndexSet) {
|
1307
|
+
this.group.attr({ zIndex: this.group.zIndex * 10 });
|
1308
|
+
this.zIndexSet = true; // #4062 set zindex only once
|
1309
|
+
}
|
1310
|
+
|
1311
|
+
var options = this.options,
|
1312
|
+
states = this.options.states;
|
1313
|
+
|
1314
|
+
this.borderWidth = options.borderWidth = defined(options.edgeWidth) ? options.edgeWidth : 1; //#4055
|
1315
|
+
|
1316
|
+
Highcharts.each(this.data, function (point) {
|
1317
|
+
if (point.y !== null) {
|
1318
|
+
var pointAttr = point.pointAttr;
|
1319
|
+
|
1320
|
+
// Set the border color to the fill color to provide a smooth edge
|
1321
|
+
this.borderColor = Highcharts.pick(options.edgeColor, pointAttr[''].fill);
|
1322
|
+
|
1323
|
+
pointAttr[''].stroke = this.borderColor;
|
1324
|
+
pointAttr.hover.stroke = Highcharts.pick(states.hover.edgeColor, this.borderColor);
|
1325
|
+
pointAttr.select.stroke = Highcharts.pick(states.select.edgeColor, this.borderColor);
|
1326
|
+
}
|
1327
|
+
});
|
1328
|
+
}
|
1329
|
+
|
1330
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1331
|
+
}
|
1332
|
+
|
1333
|
+
Highcharts.wrap(Highcharts.Series.prototype, 'alignDataLabel', function (proceed) {
|
1334
|
+
|
1335
|
+
// Only do this for 3D columns and columnranges
|
1336
|
+
if (this.chart.is3d() && (this.type === 'column' || this.type === 'columnrange')) {
|
1337
|
+
var series = this,
|
1338
|
+
chart = series.chart;
|
1339
|
+
|
1340
|
+
var args = arguments,
|
1341
|
+
alignTo = args[4];
|
1342
|
+
|
1343
|
+
var pos = ({ x: alignTo.x, y: alignTo.y, z: series.z });
|
1344
|
+
pos = perspective([pos], chart, true)[0];
|
1345
|
+
alignTo.x = pos.x;
|
1346
|
+
alignTo.y = pos.y;
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1350
|
+
});
|
1351
|
+
|
1352
|
+
if (Highcharts.seriesTypes.columnrange) {
|
1353
|
+
Highcharts.wrap(Highcharts.seriesTypes.columnrange.prototype, 'drawPoints', draw3DPoints);
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'drawPoints', draw3DPoints);
|
1357
|
+
|
1358
|
+
/***
|
1359
|
+
EXTENSION FOR 3D CYLINDRICAL COLUMNS
|
1360
|
+
Not supported
|
1361
|
+
***/
|
1362
|
+
/*
|
1363
|
+
var defaultOptions = Highcharts.getOptions();
|
1364
|
+
defaultOptions.plotOptions.cylinder = Highcharts.merge(defaultOptions.plotOptions.column);
|
1365
|
+
var CylinderSeries = Highcharts.extendClass(Highcharts.seriesTypes.column, {
|
1366
|
+
type: 'cylinder'
|
1367
|
+
});
|
1368
|
+
Highcharts.seriesTypes.cylinder = CylinderSeries;
|
1369
|
+
|
1370
|
+
Highcharts.wrap(Highcharts.seriesTypes.cylinder.prototype, 'translate', function (proceed) {
|
1371
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1372
|
+
|
1373
|
+
// Do not do this if the chart is not 3D
|
1374
|
+
if (!this.chart.is3d()) {
|
1375
|
+
return;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
var series = this,
|
1379
|
+
chart = series.chart,
|
1380
|
+
options = chart.options,
|
1381
|
+
cylOptions = options.plotOptions.cylinder,
|
1382
|
+
options3d = options.chart.options3d,
|
1383
|
+
depth = cylOptions.depth || 0,
|
1384
|
+
alpha = options3d.alpha;
|
1385
|
+
|
1386
|
+
var z = cylOptions.stacking ? (this.options.stack || 0) * depth : series._i * depth;
|
1387
|
+
z += depth / 2;
|
1388
|
+
|
1389
|
+
if (cylOptions.grouping !== false) { z = 0; }
|
1390
|
+
|
1391
|
+
Highcharts.each(series.data, function (point) {
|
1392
|
+
var shapeArgs = point.shapeArgs;
|
1393
|
+
point.shapeType = 'arc3d';
|
1394
|
+
shapeArgs.x += depth / 2;
|
1395
|
+
shapeArgs.z = z;
|
1396
|
+
shapeArgs.start = 0;
|
1397
|
+
shapeArgs.end = 2 * PI;
|
1398
|
+
shapeArgs.r = depth * 0.95;
|
1399
|
+
shapeArgs.innerR = 0;
|
1400
|
+
shapeArgs.depth = shapeArgs.height * (1 / sin((90 - alpha) * deg2rad)) - z;
|
1401
|
+
shapeArgs.alpha = 90 - alpha;
|
1402
|
+
shapeArgs.beta = 0;
|
1403
|
+
});
|
1404
|
+
});
|
1405
|
+
*/
|
1406
|
+
/***
|
1407
|
+
EXTENSION FOR 3D PIES
|
1408
|
+
***/
|
1409
|
+
|
1410
|
+
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'translate', function (proceed) {
|
1411
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1412
|
+
|
1413
|
+
// Do not do this if the chart is not 3D
|
1414
|
+
if (!this.chart.is3d()) {
|
1415
|
+
return;
|
1416
|
+
}
|
1417
|
+
|
1418
|
+
var series = this,
|
1419
|
+
chart = series.chart,
|
1420
|
+
options = chart.options,
|
1421
|
+
seriesOptions = series.options,
|
1422
|
+
depth = seriesOptions.depth || 0,
|
1423
|
+
options3d = options.chart.options3d,
|
1424
|
+
alpha = options3d.alpha,
|
1425
|
+
beta = options3d.beta,
|
1426
|
+
z = seriesOptions.stacking ? (seriesOptions.stack || 0) * depth : series._i * depth;
|
1427
|
+
|
1428
|
+
z += depth / 2;
|
1429
|
+
|
1430
|
+
if (seriesOptions.grouping !== false) {
|
1431
|
+
z = 0;
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
each(series.data, function (point) {
|
1435
|
+
|
1436
|
+
var shapeArgs = point.shapeArgs,
|
1437
|
+
angle;
|
1438
|
+
|
1439
|
+
point.shapeType = 'arc3d';
|
1440
|
+
|
1441
|
+
shapeArgs.z = z;
|
1442
|
+
shapeArgs.depth = depth * 0.75;
|
1443
|
+
shapeArgs.alpha = alpha;
|
1444
|
+
shapeArgs.beta = beta;
|
1445
|
+
shapeArgs.center = series.center;
|
1446
|
+
|
1447
|
+
angle = (shapeArgs.end + shapeArgs.start) / 2;
|
1448
|
+
|
1449
|
+
point.slicedTranslation = {
|
1450
|
+
translateX: round(cos(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad)),
|
1451
|
+
translateY: round(sin(angle) * seriesOptions.slicedOffset * cos(alpha * deg2rad))
|
1452
|
+
};
|
1453
|
+
});
|
1454
|
+
});
|
1455
|
+
|
1456
|
+
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype.pointClass.prototype, 'haloPath', function (proceed) {
|
1457
|
+
var args = arguments;
|
1458
|
+
return this.series.chart.is3d() ? [] : proceed.call(this, args[1]);
|
1459
|
+
});
|
1460
|
+
|
1461
|
+
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'drawPoints', function (proceed) {
|
1462
|
+
|
1463
|
+
var options = this.options,
|
1464
|
+
states = options.states;
|
1465
|
+
|
1466
|
+
// Do not do this if the chart is not 3D
|
1467
|
+
if (this.chart.is3d()) {
|
1468
|
+
// Set the border color to the fill color to provide a smooth edge
|
1469
|
+
this.borderWidth = options.borderWidth = options.edgeWidth || 1;
|
1470
|
+
this.borderColor = options.edgeColor = Highcharts.pick(options.edgeColor, options.borderColor, undefined);
|
1471
|
+
|
1472
|
+
states.hover.borderColor = Highcharts.pick(states.hover.edgeColor, this.borderColor);
|
1473
|
+
states.hover.borderWidth = Highcharts.pick(states.hover.edgeWidth, this.borderWidth);
|
1474
|
+
states.select.borderColor = Highcharts.pick(states.select.edgeColor, this.borderColor);
|
1475
|
+
states.select.borderWidth = Highcharts.pick(states.select.edgeWidth, this.borderWidth);
|
1476
|
+
|
1477
|
+
each(this.data, function (point) {
|
1478
|
+
var pointAttr = point.pointAttr;
|
1479
|
+
pointAttr[''].stroke = point.series.borderColor || point.color;
|
1480
|
+
pointAttr['']['stroke-width'] = point.series.borderWidth;
|
1481
|
+
pointAttr.hover.stroke = states.hover.borderColor;
|
1482
|
+
pointAttr.hover['stroke-width'] = states.hover.borderWidth;
|
1483
|
+
pointAttr.select.stroke = states.select.borderColor;
|
1484
|
+
pointAttr.select['stroke-width'] = states.select.borderWidth;
|
1485
|
+
});
|
1486
|
+
}
|
1487
|
+
|
1488
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1489
|
+
|
1490
|
+
if (this.chart.is3d()) {
|
1491
|
+
each(this.points, function (point) {
|
1492
|
+
var graphic = point.graphic;
|
1493
|
+
|
1494
|
+
// #4584 Check if has graphic - null points don't have it
|
1495
|
+
if (graphic) {
|
1496
|
+
// Hide null or 0 points (#3006, 3650)
|
1497
|
+
graphic[point.y ? 'show' : 'hide']();
|
1498
|
+
}
|
1499
|
+
});
|
1500
|
+
}
|
1501
|
+
});
|
1502
|
+
|
1503
|
+
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'drawDataLabels', function (proceed) {
|
1504
|
+
if (this.chart.is3d()) {
|
1505
|
+
var series = this,
|
1506
|
+
chart = series.chart,
|
1507
|
+
options3d = chart.options.chart.options3d;
|
1508
|
+
each(series.data, function (point) {
|
1509
|
+
var shapeArgs = point.shapeArgs,
|
1510
|
+
r = shapeArgs.r,
|
1511
|
+
a1 = (shapeArgs.alpha || options3d.alpha) * deg2rad, //#3240 issue with datalabels for 0 and null values
|
1512
|
+
b1 = (shapeArgs.beta || options3d.beta) * deg2rad,
|
1513
|
+
a2 = (shapeArgs.start + shapeArgs.end) / 2,
|
1514
|
+
labelPos = point.labelPos,
|
1515
|
+
labelIndexes = [0, 2, 4], // [x1, y1, x2, y2, x3, y3]
|
1516
|
+
yOffset = (-r * (1 - cos(a1)) * sin(a2)), // + (sin(a2) > 0 ? sin(a1) * d : 0)
|
1517
|
+
xOffset = r * (cos(b1) - 1) * cos(a2);
|
1518
|
+
|
1519
|
+
// Apply perspective on label positions
|
1520
|
+
each(labelIndexes, function (index) {
|
1521
|
+
labelPos[index] += xOffset;
|
1522
|
+
labelPos[index + 1] += yOffset;
|
1523
|
+
});
|
1524
|
+
});
|
1525
|
+
}
|
1526
|
+
|
1527
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1528
|
+
});
|
1529
|
+
|
1530
|
+
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'addPoint', function (proceed) {
|
1531
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1532
|
+
if (this.chart.is3d()) {
|
1533
|
+
// destroy (and rebuild) everything!!!
|
1534
|
+
this.update(this.userOptions, true); // #3845 pass the old options
|
1535
|
+
}
|
1536
|
+
});
|
1537
|
+
|
1538
|
+
Highcharts.wrap(Highcharts.seriesTypes.pie.prototype, 'animate', function (proceed) {
|
1539
|
+
if (!this.chart.is3d()) {
|
1540
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1541
|
+
} else {
|
1542
|
+
var args = arguments,
|
1543
|
+
init = args[1],
|
1544
|
+
animation = this.options.animation,
|
1545
|
+
attribs,
|
1546
|
+
center = this.center,
|
1547
|
+
group = this.group,
|
1548
|
+
markerGroup = this.markerGroup;
|
1549
|
+
|
1550
|
+
if (Highcharts.svg) { // VML is too slow anyway
|
1551
|
+
|
1552
|
+
if (animation === true) {
|
1553
|
+
animation = {};
|
1554
|
+
}
|
1555
|
+
// Initialize the animation
|
1556
|
+
if (init) {
|
1557
|
+
|
1558
|
+
// Scale down the group and place it in the center
|
1559
|
+
group.oldtranslateX = group.translateX;
|
1560
|
+
group.oldtranslateY = group.translateY;
|
1561
|
+
attribs = {
|
1562
|
+
translateX: center[0],
|
1563
|
+
translateY: center[1],
|
1564
|
+
scaleX: 0.001, // #1499
|
1565
|
+
scaleY: 0.001
|
1566
|
+
};
|
1567
|
+
|
1568
|
+
group.attr(attribs);
|
1569
|
+
if (markerGroup) {
|
1570
|
+
markerGroup.attrSetters = group.attrSetters;
|
1571
|
+
markerGroup.attr(attribs);
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
// Run the animation
|
1575
|
+
} else {
|
1576
|
+
attribs = {
|
1577
|
+
translateX: group.oldtranslateX,
|
1578
|
+
translateY: group.oldtranslateY,
|
1579
|
+
scaleX: 1,
|
1580
|
+
scaleY: 1
|
1581
|
+
};
|
1582
|
+
group.animate(attribs, animation);
|
1583
|
+
|
1584
|
+
if (markerGroup) {
|
1585
|
+
markerGroup.animate(attribs, animation);
|
1586
|
+
}
|
1587
|
+
|
1588
|
+
// Delete this function to allow it only once
|
1589
|
+
this.animate = null;
|
1590
|
+
}
|
1591
|
+
|
1592
|
+
}
|
1593
|
+
}
|
1594
|
+
});
|
1595
|
+
/***
|
1596
|
+
EXTENSION FOR 3D SCATTER CHART
|
1597
|
+
***/
|
1598
|
+
|
1599
|
+
Highcharts.wrap(Highcharts.seriesTypes.scatter.prototype, 'translate', function (proceed) {
|
1600
|
+
//function translate3d(proceed) {
|
1601
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1602
|
+
|
1603
|
+
if (!this.chart.is3d()) {
|
1604
|
+
return;
|
1605
|
+
}
|
1606
|
+
|
1607
|
+
var series = this,
|
1608
|
+
chart = series.chart,
|
1609
|
+
zAxis = Highcharts.pick(series.zAxis, chart.options.zAxis[0]),
|
1610
|
+
rawPoints = [],
|
1611
|
+
rawPoint,
|
1612
|
+
projectedPoints,
|
1613
|
+
projectedPoint,
|
1614
|
+
zValue,
|
1615
|
+
i;
|
1616
|
+
|
1617
|
+
for (i = 0; i < series.data.length; i++) {
|
1618
|
+
rawPoint = series.data[i];
|
1619
|
+
zValue = zAxis.isLog && zAxis.val2lin ? zAxis.val2lin(rawPoint.z) : rawPoint.z; // #4562
|
1620
|
+
rawPoint.plotZ = zAxis.translate(zValue);
|
1621
|
+
|
1622
|
+
rawPoint.isInside = rawPoint.isInside ? (zValue >= zAxis.min && zValue <= zAxis.max) : false;
|
1623
|
+
|
1624
|
+
rawPoints.push({
|
1625
|
+
x: rawPoint.plotX,
|
1626
|
+
y: rawPoint.plotY,
|
1627
|
+
z: rawPoint.plotZ
|
1628
|
+
});
|
1629
|
+
}
|
1630
|
+
|
1631
|
+
projectedPoints = perspective(rawPoints, chart, true);
|
1632
|
+
|
1633
|
+
for (i = 0; i < series.data.length; i++) {
|
1634
|
+
rawPoint = series.data[i];
|
1635
|
+
projectedPoint = projectedPoints[i];
|
1636
|
+
|
1637
|
+
rawPoint.plotXold = rawPoint.plotX;
|
1638
|
+
rawPoint.plotYold = rawPoint.plotY;
|
1639
|
+
|
1640
|
+
rawPoint.plotX = projectedPoint.x;
|
1641
|
+
rawPoint.plotY = projectedPoint.y;
|
1642
|
+
rawPoint.plotZ = projectedPoint.z;
|
1643
|
+
|
1644
|
+
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
});
|
1648
|
+
|
1649
|
+
Highcharts.wrap(Highcharts.seriesTypes.scatter.prototype, 'init', function (proceed, chart, options) {
|
1650
|
+
if (chart.is3d()) {
|
1651
|
+
// add a third coordinate
|
1652
|
+
this.axisTypes = ['xAxis', 'yAxis', 'zAxis'];
|
1653
|
+
this.pointArrayMap = ['x', 'y', 'z'];
|
1654
|
+
this.parallelArrays = ['x', 'y', 'z'];
|
1655
|
+
}
|
1656
|
+
|
1657
|
+
var result = proceed.apply(this, [chart, options]);
|
1658
|
+
|
1659
|
+
if (this.chart.is3d()) {
|
1660
|
+
// Set a new default tooltip formatter
|
1661
|
+
var default3dScatterTooltip = 'x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>z: <b>{point.z}</b><br/>';
|
1662
|
+
if (this.userOptions.tooltip) {
|
1663
|
+
this.tooltipOptions.pointFormat = this.userOptions.tooltip.pointFormat || default3dScatterTooltip;
|
1664
|
+
} else {
|
1665
|
+
this.tooltipOptions.pointFormat = default3dScatterTooltip;
|
1666
|
+
}
|
1667
|
+
}
|
1668
|
+
return result;
|
1669
|
+
});
|
1670
|
+
/**
|
1671
|
+
* Extension to the VML Renderer
|
1672
|
+
*/
|
1673
|
+
if (Highcharts.VMLRenderer) {
|
1674
|
+
|
1675
|
+
Highcharts.setOptions({ animate: false });
|
1676
|
+
|
1677
|
+
Highcharts.VMLRenderer.prototype.cuboid = Highcharts.SVGRenderer.prototype.cuboid;
|
1678
|
+
Highcharts.VMLRenderer.prototype.cuboidPath = Highcharts.SVGRenderer.prototype.cuboidPath;
|
1679
|
+
|
1680
|
+
Highcharts.VMLRenderer.prototype.toLinePath = Highcharts.SVGRenderer.prototype.toLinePath;
|
1681
|
+
|
1682
|
+
Highcharts.VMLRenderer.prototype.createElement3D = Highcharts.SVGRenderer.prototype.createElement3D;
|
1683
|
+
|
1684
|
+
Highcharts.VMLRenderer.prototype.arc3d = function (shapeArgs) {
|
1685
|
+
var result = Highcharts.SVGRenderer.prototype.arc3d.call(this, shapeArgs);
|
1686
|
+
result.css({ zIndex: result.zIndex });
|
1687
|
+
return result;
|
1688
|
+
};
|
1689
|
+
|
1690
|
+
Highcharts.VMLRenderer.prototype.arc3dPath = Highcharts.SVGRenderer.prototype.arc3dPath;
|
1691
|
+
|
1692
|
+
Highcharts.wrap(Highcharts.Axis.prototype, 'render', function (proceed) {
|
1693
|
+
proceed.apply(this, [].slice.call(arguments, 1));
|
1694
|
+
// VML doesn't support a negative z-index
|
1695
|
+
if (this.sideFrame) {
|
1696
|
+
this.sideFrame.css({ zIndex: 0 });
|
1697
|
+
this.sideFrame.front.attr({ fill: this.sideFrame.color });
|
1698
|
+
}
|
1699
|
+
if (this.bottomFrame) {
|
1700
|
+
this.bottomFrame.css({ zIndex: 1 });
|
1701
|
+
this.bottomFrame.front.attr({ fill: this.bottomFrame.color });
|
1702
|
+
}
|
1703
|
+
if (this.backFrame) {
|
1704
|
+
this.backFrame.css({ zIndex: 0 });
|
1705
|
+
this.backFrame.front.attr({ fill: this.backFrame.color });
|
1706
|
+
}
|
1707
|
+
});
|
1708
|
+
|
1709
|
+
}
|
1710
|
+
|
1711
|
+
}));
|