highcharts-rails 5.0.11 → 5.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.markdown +32 -0
  3. data/app/assets/javascripts/highcharts.js +1199 -379
  4. data/app/assets/javascripts/highcharts/highcharts-3d.js +1542 -209
  5. data/app/assets/javascripts/highcharts/highcharts-more.js +6 -1
  6. data/app/assets/javascripts/highcharts/modules/accessibility.js +13 -6
  7. data/app/assets/javascripts/highcharts/modules/annotations.js +1 -1
  8. data/app/assets/javascripts/highcharts/modules/boost.js +66 -24
  9. data/app/assets/javascripts/highcharts/modules/broken-axis.js +1 -1
  10. data/app/assets/javascripts/highcharts/modules/data.js +1 -1
  11. data/app/assets/javascripts/highcharts/modules/drilldown.js +6 -44
  12. data/app/assets/javascripts/highcharts/modules/exporting.js +8 -4
  13. data/app/assets/javascripts/highcharts/modules/funnel.js +1 -8
  14. data/app/assets/javascripts/highcharts/modules/grid-axis.js +1 -1
  15. data/app/assets/javascripts/highcharts/modules/heatmap.js +17 -51
  16. data/app/assets/javascripts/highcharts/modules/no-data-to-display.js +19 -10
  17. data/app/assets/javascripts/highcharts/modules/offline-exporting.js +7 -2
  18. data/app/assets/javascripts/highcharts/modules/overlapping-datalabels.js +1 -1
  19. data/app/assets/javascripts/highcharts/modules/series-label.js +1 -1
  20. data/app/assets/javascripts/highcharts/modules/solid-gauge.js +7 -51
  21. data/app/assets/javascripts/highcharts/modules/stock.js +82 -9
  22. data/app/assets/javascripts/highcharts/modules/treemap.js +1 -1
  23. data/app/assets/javascripts/highcharts/modules/xrange-series.js +1 -1
  24. data/lib/highcharts/version.rb +1 -1
  25. metadata +1 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Highcharts JS v5.0.11 (2017-05-04)
2
+ * @license Highcharts JS v5.0.12 (2017-05-24)
3
3
  *
4
4
  * 3D features for Highcharts JS
5
5
  *
@@ -134,6 +134,29 @@
134
134
  return distance;
135
135
  };
136
136
 
137
+ /**
138
+ * Calculate area of a 2D polygon using Shoelace algorithm
139
+ * http://en.wikipedia.org/wiki/Shoelace_formula
140
+ */
141
+ H.shapeArea = function(vertexes) {
142
+ var area = 0,
143
+ i,
144
+ j;
145
+ for (i = 0; i < vertexes.length; i++) {
146
+ j = (i + 1) % vertexes.length;
147
+ area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
148
+ }
149
+ return area / 2;
150
+ };
151
+
152
+ /**
153
+ * Calculate area of a 3D polygon after perspective projection
154
+ */
155
+ H.shapeArea3d = function(vertexes, chart, insidePlotArea) {
156
+ return H.shapeArea(H.perspective(vertexes, chart, insidePlotArea));
157
+ };
158
+
159
+
137
160
  }(Highcharts));
138
161
  (function(H) {
139
162
  /**
@@ -168,19 +191,6 @@
168
191
 
169
192
  var dFactor = (4 * (Math.sqrt(2) - 1) / 3) / (PI / 2);
170
193
 
171
-
172
- //Shoelace algorithm -- http://en.wikipedia.org/wiki/Shoelace_formula
173
- function shapeArea(vertexes) {
174
- var area = 0,
175
- i,
176
- j;
177
- for (i = 0; i < vertexes.length; i++) {
178
- j = (i + 1) % vertexes.length;
179
- area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
180
- }
181
- return area / 2;
182
- }
183
-
184
194
  /** Method to construct a curved path
185
195
  * Can 'wrap' around more then 180 degrees
186
196
  */
@@ -232,6 +242,139 @@
232
242
  return result;
233
243
  };
234
244
 
245
+ SVGRenderer.prototype.toLineSegments = function(points) {
246
+ var result = [];
247
+
248
+ var m = true;
249
+ each(points, function(point) {
250
+ result.push(m ? 'M' : 'L', point.x, point.y);
251
+ m = !m;
252
+ });
253
+
254
+ return result;
255
+ };
256
+
257
+ /**
258
+ * A 3-D Face is defined by it's 3D vertexes, and is only
259
+ * visible if it's vertexes are counter-clockwise (Back-face culling).
260
+ * It is used as a polyhedron Element
261
+ */
262
+ SVGRenderer.prototype.face3d = function(args) {
263
+ var renderer = this,
264
+ ret = this.createElement('path');
265
+ ret.vertexes = [];
266
+ ret.insidePlotArea = false;
267
+ ret.enabled = true;
268
+
269
+ wrap(ret, 'attr', function(proceed, hash) {
270
+ if (typeof hash === 'object' &&
271
+ (defined(hash.enabled) || defined(hash.vertexes) || defined(hash.insidePlotArea))) {
272
+ this.enabled = pick(hash.enabled, this.enabled);
273
+ this.vertexes = pick(hash.vertexes, this.vertexes);
274
+ this.insidePlotArea = pick(hash.insidePlotArea, this.insidePlotArea);
275
+ delete hash.enabled;
276
+ delete hash.vertexes;
277
+ delete hash.insidePlotArea;
278
+
279
+ var chart = charts[renderer.chartIndex],
280
+ vertexes2d = perspective(this.vertexes, chart, this.insidePlotArea),
281
+ path = renderer.toLinePath(vertexes2d, true),
282
+ area = H.shapeArea(vertexes2d),
283
+ visibility = (this.enabled && area > 0) ? 'visible' : 'hidden';
284
+
285
+ hash.d = path;
286
+ hash.visibility = visibility;
287
+ }
288
+ return proceed.apply(this, [].slice.call(arguments, 1));
289
+ });
290
+
291
+ wrap(ret, 'animate', function(proceed, params) {
292
+ if (typeof params === 'object' &&
293
+ (defined(params.enabled) || defined(params.vertexes) || defined(params.insidePlotArea))) {
294
+ this.enabled = pick(params.enabled, this.enabled);
295
+ this.vertexes = pick(params.vertexes, this.vertexes);
296
+ this.insidePlotArea = pick(params.insidePlotArea, this.insidePlotArea);
297
+ delete params.enabled;
298
+ delete params.vertexes;
299
+ delete params.insidePlotArea;
300
+
301
+ var chart = charts[renderer.chartIndex],
302
+ vertexes2d = perspective(this.vertexes, chart, this.insidePlotArea),
303
+ path = renderer.toLinePath(vertexes2d, true),
304
+ area = H.shapeArea(vertexes2d),
305
+ visibility = (this.enabled && area > 0) ? 'visible' : 'hidden';
306
+
307
+ params.d = path;
308
+ this.attr('visibility', visibility);
309
+ }
310
+
311
+ return proceed.apply(this, [].slice.call(arguments, 1));
312
+ });
313
+
314
+ return ret.attr(args);
315
+ };
316
+
317
+ /**
318
+ * A Polyhedron is a handy way of defining a group of 3-D faces.
319
+ * It's only attribute is `faces`, an array of attributes of each one of it's Face3D instances.
320
+ */
321
+ SVGRenderer.prototype.polyhedron = function(args) {
322
+ var renderer = this,
323
+ result = this.g(),
324
+ destroy = result.destroy;
325
+
326
+
327
+ result.attr({
328
+ 'stroke-linejoin': 'round'
329
+ });
330
+
331
+
332
+ result.faces = [];
333
+
334
+
335
+ // destroy all children
336
+ result.destroy = function() {
337
+ for (var i = 0; i < result.faces.length; i++) {
338
+ result.faces[i].destroy();
339
+ }
340
+ return destroy.call(this);
341
+ };
342
+
343
+ wrap(result, 'attr', function(proceed, hash, val, complete, continueAnimation) {
344
+ if (typeof hash === 'object' && defined(hash.faces)) {
345
+ while (result.faces.length > hash.faces.length) {
346
+ result.faces.pop().destroy();
347
+ }
348
+ while (result.faces.length < hash.faces.length) {
349
+ result.faces.push(renderer.face3d().add(result));
350
+ }
351
+ for (var i = 0; i < hash.faces.length; i++) {
352
+ result.faces[i].attr(hash.faces[i], null, complete, continueAnimation);
353
+ }
354
+ delete hash.faces;
355
+ }
356
+ return proceed.apply(this, [].slice.call(arguments, 1));
357
+ });
358
+
359
+ wrap(result, 'animate', function(proceed, params, duration, complete) {
360
+ if (params && params.faces) {
361
+ while (result.faces.length > params.faces.length) {
362
+ result.faces.pop().destroy();
363
+ }
364
+ while (result.faces.length < params.faces.length) {
365
+ result.faces.push(renderer.face3d().add(result));
366
+ }
367
+ for (var i = 0; i < params.faces.length; i++) {
368
+ result.faces[i].animate(params.faces[i], duration, complete);
369
+ }
370
+ delete params.faces;
371
+ }
372
+ return proceed.apply(this, [].slice.call(arguments, 1));
373
+ });
374
+
375
+ return result.attr(args);
376
+ };
377
+
235
378
  ////// CUBOIDS //////
236
379
  SVGRenderer.prototype.cuboid = function(shapeArgs) {
237
380
 
@@ -445,9 +588,9 @@
445
588
  ];
446
589
  path1 = map(path1, mapPath);
447
590
  path2 = map(path2, mapPath);
448
- if (shapeArea(path1) < 0) {
591
+ if (H.shapeArea(path1) < 0) {
449
592
  ret = [path1, 0];
450
- } else if (shapeArea(path2) < 0) {
593
+ } else if (H.shapeArea(path2) < 0) {
451
594
  ret = [path2, 1];
452
595
  }
453
596
  return ret;
@@ -1049,16 +1192,16 @@
1049
1192
  depth: 100,
1050
1193
  fitToPlot: true,
1051
1194
  viewDistance: 25,
1195
+ axisLabelPosition: 'default',
1052
1196
  frame: {
1053
- bottom: {
1054
- size: 1
1055
- },
1056
- side: {
1057
- size: 1
1058
- },
1059
- back: {
1060
- size: 1
1061
- }
1197
+ visible: 'default',
1198
+ size: 1,
1199
+ bottom: {},
1200
+ top: {},
1201
+ left: {},
1202
+ right: {},
1203
+ back: {},
1204
+ front: {}
1062
1205
  }
1063
1206
  }
1064
1207
  }
@@ -1106,6 +1249,14 @@
1106
1249
  if (this.is3d()) {
1107
1250
  // Set to force a redraw of all elements
1108
1251
  this.isDirtyBox = true;
1252
+ this.frame3d = this.get3dFrame();
1253
+ }
1254
+ proceed.apply(this, [].slice.call(arguments, 1));
1255
+ });
1256
+
1257
+ wrap(Chart.prototype, 'render', function(proceed) {
1258
+ if (this.is3d()) {
1259
+ this.frame3d = this.get3dFrame();
1109
1260
  }
1110
1261
  proceed.apply(this, [].slice.call(arguments, 1));
1111
1262
  });
@@ -1126,6 +1277,830 @@
1126
1277
  }
1127
1278
  });
1128
1279
 
1280
+ wrap(Chart.prototype, 'drawChartBox', function(proceed) {
1281
+ if (this.is3d()) {
1282
+ var chart = this,
1283
+ renderer = chart.renderer,
1284
+ options3d = this.options.chart.options3d,
1285
+ frame = chart.get3dFrame(),
1286
+ xm = this.plotLeft,
1287
+ xp = this.plotLeft + this.plotWidth,
1288
+ ym = this.plotTop,
1289
+ yp = this.plotTop + this.plotHeight,
1290
+ zm = 0,
1291
+ zp = options3d.depth,
1292
+ xmm = xm - (frame.left.visible ? frame.left.size : 0),
1293
+ xpp = xp + (frame.right.visible ? frame.right.size : 0),
1294
+ ymm = ym - (frame.top.visible ? frame.top.size : 0),
1295
+ ypp = yp + (frame.bottom.visible ? frame.bottom.size : 0),
1296
+ zmm = zm - (frame.front.visible ? frame.front.size : 0),
1297
+ zpp = zp + (frame.back.visible ? frame.back.size : 0),
1298
+ verb = chart.hasRendered ? 'animate' : 'attr';
1299
+
1300
+ this.frame3d = frame;
1301
+
1302
+ if (!this.frameShapes) {
1303
+ this.frameShapes = {
1304
+ bottom: renderer.polyhedron().add(),
1305
+ top: renderer.polyhedron().add(),
1306
+ left: renderer.polyhedron().add(),
1307
+ right: renderer.polyhedron().add(),
1308
+ back: renderer.polyhedron().add(),
1309
+ front: renderer.polyhedron().add()
1310
+ };
1311
+ }
1312
+
1313
+ this.frameShapes.bottom[verb]({
1314
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
1315
+ zIndex: frame.bottom.frontFacing ? -1000 : 1000,
1316
+ faces: [{ //bottom
1317
+ fill: H.color(frame.bottom.color).brighten(0.1).get(),
1318
+ vertexes: [{
1319
+ x: xmm,
1320
+ y: ypp,
1321
+ z: zmm
1322
+ }, {
1323
+ x: xpp,
1324
+ y: ypp,
1325
+ z: zmm
1326
+ }, {
1327
+ x: xpp,
1328
+ y: ypp,
1329
+ z: zpp
1330
+ }, {
1331
+ x: xmm,
1332
+ y: ypp,
1333
+ z: zpp
1334
+ }],
1335
+ enabled: frame.bottom.visible
1336
+ },
1337
+ { //top
1338
+ fill: H.color(frame.bottom.color).brighten(0.1).get(),
1339
+ vertexes: [{
1340
+ x: xm,
1341
+ y: yp,
1342
+ z: zp
1343
+ }, {
1344
+ x: xp,
1345
+ y: yp,
1346
+ z: zp
1347
+ }, {
1348
+ x: xp,
1349
+ y: yp,
1350
+ z: zm
1351
+ }, {
1352
+ x: xm,
1353
+ y: yp,
1354
+ z: zm
1355
+ }],
1356
+ enabled: frame.bottom.visible
1357
+ },
1358
+ { //left
1359
+ fill: H.color(frame.bottom.color).brighten(-0.1).get(),
1360
+ vertexes: [{
1361
+ x: xmm,
1362
+ y: ypp,
1363
+ z: zmm
1364
+ }, {
1365
+ x: xmm,
1366
+ y: ypp,
1367
+ z: zpp
1368
+ }, {
1369
+ x: xm,
1370
+ y: yp,
1371
+ z: zp
1372
+ }, {
1373
+ x: xm,
1374
+ y: yp,
1375
+ z: zm
1376
+ }],
1377
+ enabled: frame.bottom.visible && !frame.left.visible
1378
+ },
1379
+ { //right
1380
+ fill: H.color(frame.bottom.color).brighten(-0.1).get(),
1381
+ vertexes: [{
1382
+ x: xpp,
1383
+ y: ypp,
1384
+ z: zpp
1385
+ }, {
1386
+ x: xpp,
1387
+ y: ypp,
1388
+ z: zmm
1389
+ }, {
1390
+ x: xp,
1391
+ y: yp,
1392
+ z: zm
1393
+ }, {
1394
+ x: xp,
1395
+ y: yp,
1396
+ z: zp
1397
+ }],
1398
+ enabled: frame.bottom.visible && !frame.right.visible
1399
+ },
1400
+ { //front
1401
+ fill: H.color(frame.bottom.color).get(),
1402
+ vertexes: [{
1403
+ x: xpp,
1404
+ y: ypp,
1405
+ z: zmm
1406
+ }, {
1407
+ x: xmm,
1408
+ y: ypp,
1409
+ z: zmm
1410
+ }, {
1411
+ x: xm,
1412
+ y: yp,
1413
+ z: zm
1414
+ }, {
1415
+ x: xp,
1416
+ y: yp,
1417
+ z: zm
1418
+ }],
1419
+ enabled: frame.bottom.visible && !frame.front.visible
1420
+ },
1421
+ { //back
1422
+ fill: H.color(frame.bottom.color).get(),
1423
+ vertexes: [{
1424
+ x: xmm,
1425
+ y: ypp,
1426
+ z: zpp
1427
+ }, {
1428
+ x: xpp,
1429
+ y: ypp,
1430
+ z: zpp
1431
+ }, {
1432
+ x: xp,
1433
+ y: yp,
1434
+ z: zp
1435
+ }, {
1436
+ x: xm,
1437
+ y: yp,
1438
+ z: zp
1439
+ }],
1440
+ enabled: frame.bottom.visible && !frame.back.visible
1441
+ }
1442
+ ]
1443
+ });
1444
+ this.frameShapes.top[verb]({
1445
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-top',
1446
+ zIndex: frame.top.frontFacing ? -1000 : 1000,
1447
+ faces: [{ //bottom
1448
+ fill: H.color(frame.top.color).brighten(0.1).get(),
1449
+ vertexes: [{
1450
+ x: xmm,
1451
+ y: ymm,
1452
+ z: zpp
1453
+ }, {
1454
+ x: xpp,
1455
+ y: ymm,
1456
+ z: zpp
1457
+ }, {
1458
+ x: xpp,
1459
+ y: ymm,
1460
+ z: zmm
1461
+ }, {
1462
+ x: xmm,
1463
+ y: ymm,
1464
+ z: zmm
1465
+ }],
1466
+ enabled: frame.top.visible
1467
+ },
1468
+ { //top
1469
+ fill: H.color(frame.top.color).brighten(0.1).get(),
1470
+ vertexes: [{
1471
+ x: xm,
1472
+ y: ym,
1473
+ z: zm
1474
+ }, {
1475
+ x: xp,
1476
+ y: ym,
1477
+ z: zm
1478
+ }, {
1479
+ x: xp,
1480
+ y: ym,
1481
+ z: zp
1482
+ }, {
1483
+ x: xm,
1484
+ y: ym,
1485
+ z: zp
1486
+ }],
1487
+ enabled: frame.top.visible
1488
+ },
1489
+ { //left
1490
+ fill: H.color(frame.top.color).brighten(-0.1).get(),
1491
+ vertexes: [{
1492
+ x: xmm,
1493
+ y: ymm,
1494
+ z: zpp
1495
+ }, {
1496
+ x: xmm,
1497
+ y: ymm,
1498
+ z: zmm
1499
+ }, {
1500
+ x: xm,
1501
+ y: ym,
1502
+ z: zm
1503
+ }, {
1504
+ x: xm,
1505
+ y: ym,
1506
+ z: zp
1507
+ }],
1508
+ enabled: frame.top.visible && !frame.left.visible
1509
+ },
1510
+ { //right
1511
+ fill: H.color(frame.top.color).brighten(-0.1).get(),
1512
+ vertexes: [{
1513
+ x: xpp,
1514
+ y: ymm,
1515
+ z: zmm
1516
+ }, {
1517
+ x: xpp,
1518
+ y: ymm,
1519
+ z: zpp
1520
+ }, {
1521
+ x: xp,
1522
+ y: ym,
1523
+ z: zp
1524
+ }, {
1525
+ x: xp,
1526
+ y: ym,
1527
+ z: zm
1528
+ }],
1529
+ enabled: frame.top.visible && !frame.right.visible
1530
+ },
1531
+ { //front
1532
+ fill: H.color(frame.top.color).get(),
1533
+ vertexes: [{
1534
+ x: xmm,
1535
+ y: ymm,
1536
+ z: zmm
1537
+ }, {
1538
+ x: xpp,
1539
+ y: ymm,
1540
+ z: zmm
1541
+ }, {
1542
+ x: xp,
1543
+ y: ym,
1544
+ z: zm
1545
+ }, {
1546
+ x: xm,
1547
+ y: ym,
1548
+ z: zm
1549
+ }],
1550
+ enabled: frame.top.visible && !frame.front.visible
1551
+ },
1552
+ { //back
1553
+ fill: H.color(frame.top.color).get(),
1554
+ vertexes: [{
1555
+ x: xpp,
1556
+ y: ymm,
1557
+ z: zpp
1558
+ }, {
1559
+ x: xmm,
1560
+ y: ymm,
1561
+ z: zpp
1562
+ }, {
1563
+ x: xm,
1564
+ y: ym,
1565
+ z: zp
1566
+ }, {
1567
+ x: xp,
1568
+ y: ym,
1569
+ z: zp
1570
+ }],
1571
+ enabled: frame.top.visible && !frame.back.visible
1572
+ }
1573
+ ]
1574
+ });
1575
+ this.frameShapes.left[verb]({
1576
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-left',
1577
+ zIndex: frame.left.frontFacing ? -1000 : 1000,
1578
+ faces: [{ //bottom
1579
+ fill: H.color(frame.left.color).brighten(0.1).get(),
1580
+ vertexes: [{
1581
+ x: xmm,
1582
+ y: ypp,
1583
+ z: zmm
1584
+ }, {
1585
+ x: xm,
1586
+ y: yp,
1587
+ z: zm
1588
+ }, {
1589
+ x: xm,
1590
+ y: yp,
1591
+ z: zp
1592
+ }, {
1593
+ x: xmm,
1594
+ y: ypp,
1595
+ z: zpp
1596
+ }],
1597
+ enabled: frame.left.visible && !frame.bottom.visible
1598
+ },
1599
+ { //top
1600
+ fill: H.color(frame.left.color).brighten(0.1).get(),
1601
+ vertexes: [{
1602
+ x: xmm,
1603
+ y: ymm,
1604
+ z: zpp
1605
+ }, {
1606
+ x: xm,
1607
+ y: ym,
1608
+ z: zp
1609
+ }, {
1610
+ x: xm,
1611
+ y: ym,
1612
+ z: zm
1613
+ }, {
1614
+ x: xmm,
1615
+ y: ymm,
1616
+ z: zmm
1617
+ }],
1618
+ enabled: frame.left.visible && !frame.top.visible
1619
+ },
1620
+ { //left
1621
+ fill: H.color(frame.left.color).brighten(-0.1).get(),
1622
+ vertexes: [{
1623
+ x: xmm,
1624
+ y: ypp,
1625
+ z: zpp
1626
+ }, {
1627
+ x: xmm,
1628
+ y: ymm,
1629
+ z: zpp
1630
+ }, {
1631
+ x: xmm,
1632
+ y: ymm,
1633
+ z: zmm
1634
+ }, {
1635
+ x: xmm,
1636
+ y: ypp,
1637
+ z: zmm
1638
+ }],
1639
+ enabled: frame.left.visible
1640
+ },
1641
+ { //right
1642
+ fill: H.color(frame.left.color).brighten(-0.1).get(),
1643
+ vertexes: [{
1644
+ x: xm,
1645
+ y: ym,
1646
+ z: zp
1647
+ }, {
1648
+ x: xm,
1649
+ y: yp,
1650
+ z: zp
1651
+ }, {
1652
+ x: xm,
1653
+ y: yp,
1654
+ z: zm
1655
+ }, {
1656
+ x: xm,
1657
+ y: ym,
1658
+ z: zm
1659
+ }],
1660
+ enabled: frame.left.visible
1661
+ },
1662
+ { //front
1663
+ fill: H.color(frame.left.color).get(),
1664
+ vertexes: [{
1665
+ x: xmm,
1666
+ y: ypp,
1667
+ z: zmm
1668
+ }, {
1669
+ x: xmm,
1670
+ y: ymm,
1671
+ z: zmm
1672
+ }, {
1673
+ x: xm,
1674
+ y: ym,
1675
+ z: zm
1676
+ }, {
1677
+ x: xm,
1678
+ y: yp,
1679
+ z: zm
1680
+ }],
1681
+ enabled: frame.left.visible && !frame.front.visible
1682
+ },
1683
+ { //back
1684
+ fill: H.color(frame.left.color).get(),
1685
+ vertexes: [{
1686
+ x: xmm,
1687
+ y: ymm,
1688
+ z: zpp
1689
+ }, {
1690
+ x: xmm,
1691
+ y: ypp,
1692
+ z: zpp
1693
+ }, {
1694
+ x: xm,
1695
+ y: yp,
1696
+ z: zp
1697
+ }, {
1698
+ x: xm,
1699
+ y: ym,
1700
+ z: zp
1701
+ }],
1702
+ enabled: frame.left.visible && !frame.back.visible
1703
+ }
1704
+ ]
1705
+ });
1706
+ this.frameShapes.right[verb]({
1707
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-right',
1708
+ zIndex: frame.right.frontFacing ? -1000 : 1000,
1709
+ faces: [{ //bottom
1710
+ fill: H.color(frame.right.color).brighten(0.1).get(),
1711
+ vertexes: [{
1712
+ x: xpp,
1713
+ y: ypp,
1714
+ z: zpp
1715
+ }, {
1716
+ x: xp,
1717
+ y: yp,
1718
+ z: zp
1719
+ }, {
1720
+ x: xp,
1721
+ y: yp,
1722
+ z: zm
1723
+ }, {
1724
+ x: xpp,
1725
+ y: ypp,
1726
+ z: zmm
1727
+ }],
1728
+ enabled: frame.right.visible && !frame.bottom.visible
1729
+ },
1730
+ { //top
1731
+ fill: H.color(frame.right.color).brighten(0.1).get(),
1732
+ vertexes: [{
1733
+ x: xpp,
1734
+ y: ymm,
1735
+ z: zmm
1736
+ }, {
1737
+ x: xp,
1738
+ y: ym,
1739
+ z: zm
1740
+ }, {
1741
+ x: xp,
1742
+ y: ym,
1743
+ z: zp
1744
+ }, {
1745
+ x: xpp,
1746
+ y: ymm,
1747
+ z: zpp
1748
+ }],
1749
+ enabled: frame.right.visible && !frame.top.visible
1750
+ },
1751
+ { //left
1752
+ fill: H.color(frame.right.color).brighten(-0.1).get(),
1753
+ vertexes: [{
1754
+ x: xp,
1755
+ y: ym,
1756
+ z: zm
1757
+ }, {
1758
+ x: xp,
1759
+ y: yp,
1760
+ z: zm
1761
+ }, {
1762
+ x: xp,
1763
+ y: yp,
1764
+ z: zp
1765
+ }, {
1766
+ x: xp,
1767
+ y: ym,
1768
+ z: zp
1769
+ }],
1770
+ enabled: frame.right.visible
1771
+ },
1772
+ { //right
1773
+ fill: H.color(frame.right.color).brighten(-0.1).get(),
1774
+ vertexes: [{
1775
+ x: xpp,
1776
+ y: ypp,
1777
+ z: zmm
1778
+ }, {
1779
+ x: xpp,
1780
+ y: ymm,
1781
+ z: zmm
1782
+ }, {
1783
+ x: xpp,
1784
+ y: ymm,
1785
+ z: zpp
1786
+ }, {
1787
+ x: xpp,
1788
+ y: ypp,
1789
+ z: zpp
1790
+ }],
1791
+ enabled: frame.right.visible
1792
+ },
1793
+ { //front
1794
+ fill: H.color(frame.right.color).get(),
1795
+ vertexes: [{
1796
+ x: xpp,
1797
+ y: ymm,
1798
+ z: zmm
1799
+ }, {
1800
+ x: xpp,
1801
+ y: ypp,
1802
+ z: zmm
1803
+ }, {
1804
+ x: xp,
1805
+ y: yp,
1806
+ z: zm
1807
+ }, {
1808
+ x: xp,
1809
+ y: ym,
1810
+ z: zm
1811
+ }],
1812
+ enabled: frame.right.visible && !frame.front.visible
1813
+ },
1814
+ { //back
1815
+ fill: H.color(frame.right.color).get(),
1816
+ vertexes: [{
1817
+ x: xpp,
1818
+ y: ypp,
1819
+ z: zpp
1820
+ }, {
1821
+ x: xpp,
1822
+ y: ymm,
1823
+ z: zpp
1824
+ }, {
1825
+ x: xp,
1826
+ y: ym,
1827
+ z: zp
1828
+ }, {
1829
+ x: xp,
1830
+ y: yp,
1831
+ z: zp
1832
+ }],
1833
+ enabled: frame.right.visible && !frame.back.visible
1834
+ }
1835
+ ]
1836
+ });
1837
+ this.frameShapes.back[verb]({
1838
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-back',
1839
+ zIndex: frame.back.frontFacing ? -1000 : 1000,
1840
+ faces: [{ //bottom
1841
+ fill: H.color(frame.back.color).brighten(0.1).get(),
1842
+ vertexes: [{
1843
+ x: xpp,
1844
+ y: ypp,
1845
+ z: zpp
1846
+ }, {
1847
+ x: xmm,
1848
+ y: ypp,
1849
+ z: zpp
1850
+ }, {
1851
+ x: xm,
1852
+ y: yp,
1853
+ z: zp
1854
+ }, {
1855
+ x: xp,
1856
+ y: yp,
1857
+ z: zp
1858
+ }],
1859
+ enabled: frame.back.visible && !frame.bottom.visible
1860
+ },
1861
+ { //top
1862
+ fill: H.color(frame.back.color).brighten(0.1).get(),
1863
+ vertexes: [{
1864
+ x: xmm,
1865
+ y: ymm,
1866
+ z: zpp
1867
+ }, {
1868
+ x: xpp,
1869
+ y: ymm,
1870
+ z: zpp
1871
+ }, {
1872
+ x: xp,
1873
+ y: ym,
1874
+ z: zp
1875
+ }, {
1876
+ x: xm,
1877
+ y: ym,
1878
+ z: zp
1879
+ }],
1880
+ enabled: frame.back.visible && !frame.top.visible
1881
+ },
1882
+ { //left
1883
+ fill: H.color(frame.back.color).brighten(-0.1).get(),
1884
+ vertexes: [{
1885
+ x: xmm,
1886
+ y: ypp,
1887
+ z: zpp
1888
+ }, {
1889
+ x: xmm,
1890
+ y: ymm,
1891
+ z: zpp
1892
+ }, {
1893
+ x: xm,
1894
+ y: ym,
1895
+ z: zp
1896
+ }, {
1897
+ x: xm,
1898
+ y: yp,
1899
+ z: zp
1900
+ }],
1901
+ enabled: frame.back.visible && !frame.left.visible
1902
+ },
1903
+ { //right
1904
+ fill: H.color(frame.back.color).brighten(-0.1).get(),
1905
+ vertexes: [{
1906
+ x: xpp,
1907
+ y: ymm,
1908
+ z: zpp
1909
+ }, {
1910
+ x: xpp,
1911
+ y: ypp,
1912
+ z: zpp
1913
+ }, {
1914
+ x: xp,
1915
+ y: yp,
1916
+ z: zp
1917
+ }, {
1918
+ x: xp,
1919
+ y: ym,
1920
+ z: zp
1921
+ }],
1922
+ enabled: frame.back.visible && !frame.right.visible
1923
+ },
1924
+ { //front
1925
+ fill: H.color(frame.back.color).get(),
1926
+ vertexes: [{
1927
+ x: xm,
1928
+ y: ym,
1929
+ z: zp
1930
+ }, {
1931
+ x: xp,
1932
+ y: ym,
1933
+ z: zp
1934
+ }, {
1935
+ x: xp,
1936
+ y: yp,
1937
+ z: zp
1938
+ }, {
1939
+ x: xm,
1940
+ y: yp,
1941
+ z: zp
1942
+ }],
1943
+ enabled: frame.back.visible
1944
+ },
1945
+ { //back
1946
+ fill: H.color(frame.back.color).get(),
1947
+ vertexes: [{
1948
+ x: xmm,
1949
+ y: ypp,
1950
+ z: zpp
1951
+ }, {
1952
+ x: xpp,
1953
+ y: ypp,
1954
+ z: zpp
1955
+ }, {
1956
+ x: xpp,
1957
+ y: ymm,
1958
+ z: zpp
1959
+ }, {
1960
+ x: xmm,
1961
+ y: ymm,
1962
+ z: zpp
1963
+ }],
1964
+ enabled: frame.back.visible
1965
+ }
1966
+ ]
1967
+ });
1968
+ this.frameShapes.front[verb]({
1969
+ 'class': 'highcharts-3d-frame highcharts-3d-frame-front',
1970
+ zIndex: frame.front.frontFacing ? -1000 : 1000,
1971
+ faces: [{ //bottom
1972
+ fill: H.color(frame.front.color).brighten(0.1).get(),
1973
+ vertexes: [{
1974
+ x: xmm,
1975
+ y: ypp,
1976
+ z: zmm
1977
+ }, {
1978
+ x: xpp,
1979
+ y: ypp,
1980
+ z: zmm
1981
+ }, {
1982
+ x: xp,
1983
+ y: yp,
1984
+ z: zm
1985
+ }, {
1986
+ x: xm,
1987
+ y: yp,
1988
+ z: zm
1989
+ }],
1990
+ enabled: frame.front.visible && !frame.bottom.visible
1991
+ },
1992
+ { //top
1993
+ fill: H.color(frame.front.color).brighten(0.1).get(),
1994
+ vertexes: [{
1995
+ x: xpp,
1996
+ y: ymm,
1997
+ z: zmm
1998
+ }, {
1999
+ x: xmm,
2000
+ y: ymm,
2001
+ z: zmm
2002
+ }, {
2003
+ x: xm,
2004
+ y: ym,
2005
+ z: zm
2006
+ }, {
2007
+ x: xp,
2008
+ y: ym,
2009
+ z: zm
2010
+ }],
2011
+ enabled: frame.front.visible && !frame.top.visible
2012
+ },
2013
+ { //left
2014
+ fill: H.color(frame.front.color).brighten(-0.1).get(),
2015
+ vertexes: [{
2016
+ x: xmm,
2017
+ y: ymm,
2018
+ z: zmm
2019
+ }, {
2020
+ x: xmm,
2021
+ y: ypp,
2022
+ z: zmm
2023
+ }, {
2024
+ x: xm,
2025
+ y: yp,
2026
+ z: zm
2027
+ }, {
2028
+ x: xm,
2029
+ y: ym,
2030
+ z: zm
2031
+ }],
2032
+ enabled: frame.front.visible && !frame.left.visible
2033
+ },
2034
+ { //right
2035
+ fill: H.color(frame.front.color).brighten(-0.1).get(),
2036
+ vertexes: [{
2037
+ x: xpp,
2038
+ y: ypp,
2039
+ z: zmm
2040
+ }, {
2041
+ x: xpp,
2042
+ y: ymm,
2043
+ z: zmm
2044
+ }, {
2045
+ x: xp,
2046
+ y: ym,
2047
+ z: zm
2048
+ }, {
2049
+ x: xp,
2050
+ y: yp,
2051
+ z: zm
2052
+ }],
2053
+ enabled: frame.front.visible && !frame.right.visible
2054
+ },
2055
+ { //front
2056
+ fill: H.color(frame.front.color).get(),
2057
+ vertexes: [{
2058
+ x: xp,
2059
+ y: ym,
2060
+ z: zm
2061
+ }, {
2062
+ x: xm,
2063
+ y: ym,
2064
+ z: zm
2065
+ }, {
2066
+ x: xm,
2067
+ y: yp,
2068
+ z: zm
2069
+ }, {
2070
+ x: xp,
2071
+ y: yp,
2072
+ z: zm
2073
+ }],
2074
+ enabled: frame.front.visible
2075
+ },
2076
+ { //back
2077
+ fill: H.color(frame.front.color).get(),
2078
+ vertexes: [{
2079
+ x: xpp,
2080
+ y: ypp,
2081
+ z: zmm
2082
+ }, {
2083
+ x: xmm,
2084
+ y: ypp,
2085
+ z: zmm
2086
+ }, {
2087
+ x: xmm,
2088
+ y: ymm,
2089
+ z: zmm
2090
+ }, {
2091
+ x: xpp,
2092
+ y: ymm,
2093
+ z: zmm
2094
+ }],
2095
+ enabled: frame.front.visible
2096
+ }
2097
+ ]
2098
+ });
2099
+ }
2100
+
2101
+ return proceed.apply(this, [].slice.call(arguments, 1));
2102
+ });
2103
+
1129
2104
  Chart.prototype.retrieveStacks = function(stacking) {
1130
2105
  var series = this.series,
1131
2106
  stacks = {},
@@ -1149,6 +2124,401 @@
1149
2124
  return stacks;
1150
2125
  };
1151
2126
 
2127
+ Chart.prototype.get3dFrame = function() {
2128
+ var chart = this,
2129
+ options3d = chart.options.chart.options3d,
2130
+ frameOptions = options3d.frame,
2131
+ xm = chart.plotLeft,
2132
+ xp = chart.plotLeft + chart.plotWidth,
2133
+ ym = chart.plotTop,
2134
+ yp = chart.plotTop + chart.plotHeight,
2135
+ zm = 0,
2136
+ zp = options3d.depth,
2137
+ bottomOrientation = H.shapeArea3d([{
2138
+ x: xm,
2139
+ y: yp,
2140
+ z: zp
2141
+ }, {
2142
+ x: xp,
2143
+ y: yp,
2144
+ z: zp
2145
+ }, {
2146
+ x: xp,
2147
+ y: yp,
2148
+ z: zm
2149
+ }, {
2150
+ x: xm,
2151
+ y: yp,
2152
+ z: zm
2153
+ }], chart),
2154
+ topOrientation = H.shapeArea3d([{
2155
+ x: xm,
2156
+ y: ym,
2157
+ z: zm
2158
+ }, {
2159
+ x: xp,
2160
+ y: ym,
2161
+ z: zm
2162
+ }, {
2163
+ x: xp,
2164
+ y: ym,
2165
+ z: zp
2166
+ }, {
2167
+ x: xm,
2168
+ y: ym,
2169
+ z: zp
2170
+ }], chart),
2171
+ leftOrientation = H.shapeArea3d([{
2172
+ x: xm,
2173
+ y: ym,
2174
+ z: zm
2175
+ }, {
2176
+ x: xm,
2177
+ y: ym,
2178
+ z: zp
2179
+ }, {
2180
+ x: xm,
2181
+ y: yp,
2182
+ z: zp
2183
+ }, {
2184
+ x: xm,
2185
+ y: yp,
2186
+ z: zm
2187
+ }], chart),
2188
+ rightOrientation = H.shapeArea3d([{
2189
+ x: xp,
2190
+ y: ym,
2191
+ z: zp
2192
+ }, {
2193
+ x: xp,
2194
+ y: ym,
2195
+ z: zm
2196
+ }, {
2197
+ x: xp,
2198
+ y: yp,
2199
+ z: zm
2200
+ }, {
2201
+ x: xp,
2202
+ y: yp,
2203
+ z: zp
2204
+ }], chart),
2205
+ frontOrientation = H.shapeArea3d([{
2206
+ x: xm,
2207
+ y: yp,
2208
+ z: zm
2209
+ }, {
2210
+ x: xp,
2211
+ y: yp,
2212
+ z: zm
2213
+ }, {
2214
+ x: xp,
2215
+ y: ym,
2216
+ z: zm
2217
+ }, {
2218
+ x: xm,
2219
+ y: ym,
2220
+ z: zm
2221
+ }], chart),
2222
+ backOrientation = H.shapeArea3d([{
2223
+ x: xm,
2224
+ y: ym,
2225
+ z: zp
2226
+ }, {
2227
+ x: xp,
2228
+ y: ym,
2229
+ z: zp
2230
+ }, {
2231
+ x: xp,
2232
+ y: yp,
2233
+ z: zp
2234
+ }, {
2235
+ x: xm,
2236
+ y: yp,
2237
+ z: zp
2238
+ }], chart),
2239
+ defaultShowBottom = false,
2240
+ defaultShowTop = false,
2241
+ defaultShowLeft = false,
2242
+ defaultShowRight = false,
2243
+ defaultShowFront = false,
2244
+ defaultShowBack = true;
2245
+
2246
+ // The 'default' criteria to visible faces of the frame is looking up every
2247
+ // axis to decide whenever the left/right//top/bottom sides of the frame
2248
+ // will be shown
2249
+ each([].concat(chart.xAxis, chart.yAxis, chart.zAxis), function(axis) {
2250
+ if (axis) {
2251
+ if (axis.horiz) {
2252
+ if (axis.opposite) {
2253
+ defaultShowTop = true;
2254
+ } else {
2255
+ defaultShowBottom = true;
2256
+ }
2257
+ } else {
2258
+ if (axis.opposite) {
2259
+ defaultShowRight = true;
2260
+ } else {
2261
+ defaultShowLeft = true;
2262
+ }
2263
+ }
2264
+ }
2265
+ });
2266
+
2267
+ var getFaceOptions = function(sources, faceOrientation, defaultVisible) {
2268
+ var faceAttrs = ['size', 'color', 'visible'];
2269
+ var options = {};
2270
+ for (var i = 0; i < faceAttrs.length; i++) {
2271
+ var attr = faceAttrs[i];
2272
+ for (var j = 0; j < sources.length; j++) {
2273
+ if (typeof sources[j] === 'object') {
2274
+ var val = sources[j][attr];
2275
+ if (val !== undefined && val !== null) {
2276
+ options[attr] = val;
2277
+ break;
2278
+ }
2279
+ }
2280
+ }
2281
+ }
2282
+ var isVisible = defaultVisible;
2283
+ if (options.visible === true || options.visible === false) {
2284
+ isVisible = options.visible;
2285
+ } else if (options.visible === 'auto') {
2286
+ isVisible = faceOrientation >= 0;
2287
+ }
2288
+
2289
+ return {
2290
+ size: pick(options.size, 1),
2291
+ color: pick(options.color, 'none'),
2292
+ frontFacing: faceOrientation > 0,
2293
+ visible: isVisible
2294
+ };
2295
+ };
2296
+
2297
+ // docs @TODO: Add all frame options (left, right, top, bottom, front, back) to
2298
+ // apioptions JSDoc once the new system is up.
2299
+ var ret = {
2300
+ // FIXME: Previously, left/right, top/bottom and front/back pairs shared
2301
+ // size and color.
2302
+ // For compatibility and consistency sake, when one face have
2303
+ // size/color/visibility set, the opposite face will default to the same
2304
+ // values. Also, left/right used to be called 'side', so that's also
2305
+ // added as a fallback
2306
+ bottom: getFaceOptions(
2307
+ [frameOptions.bottom, frameOptions.top, frameOptions],
2308
+ bottomOrientation,
2309
+ defaultShowBottom
2310
+ ),
2311
+ top: getFaceOptions(
2312
+ [frameOptions.top, frameOptions.bottom, frameOptions],
2313
+ topOrientation,
2314
+ defaultShowTop
2315
+ ),
2316
+ left: getFaceOptions(
2317
+ [
2318
+ frameOptions.left,
2319
+ frameOptions.right,
2320
+ frameOptions.side,
2321
+ frameOptions
2322
+ ],
2323
+ leftOrientation,
2324
+ defaultShowLeft
2325
+ ),
2326
+ right: getFaceOptions(
2327
+ [
2328
+ frameOptions.right,
2329
+ frameOptions.left,
2330
+ frameOptions.side,
2331
+ frameOptions
2332
+ ],
2333
+ rightOrientation,
2334
+ defaultShowRight
2335
+ ),
2336
+ back: getFaceOptions(
2337
+ [frameOptions.back, frameOptions.front, frameOptions],
2338
+ backOrientation,
2339
+ defaultShowBack
2340
+ ),
2341
+ front: getFaceOptions(
2342
+ [frameOptions.front, frameOptions.back, frameOptions],
2343
+ frontOrientation,
2344
+ defaultShowFront
2345
+ )
2346
+ };
2347
+
2348
+
2349
+ // Decide the bast place to put axis title/labels based on the visible faces.
2350
+ // Ideally, The labels can only be on the edge between a visible face and an invisble one.
2351
+ // Also, the Y label should be one the left-most edge (right-most if opposite),
2352
+ if (options3d.axisLabelPosition === 'auto') {
2353
+ var isValidEdge = function(face1, face2) {
2354
+ return (face1.visible !== face2.visible) ||
2355
+ (face1.visible && face2.visible && (face1.frontFacing !== face2.frontFacing));
2356
+ };
2357
+
2358
+ var yEdges = [];
2359
+ if (isValidEdge(ret.left, ret.front)) {
2360
+ yEdges.push({
2361
+ y: (ym + yp) / 2,
2362
+ x: xm,
2363
+ z: zm
2364
+ });
2365
+ }
2366
+ if (isValidEdge(ret.left, ret.back)) {
2367
+ yEdges.push({
2368
+ y: (ym + yp) / 2,
2369
+ x: xm,
2370
+ z: zp
2371
+ });
2372
+ }
2373
+ if (isValidEdge(ret.right, ret.front)) {
2374
+ yEdges.push({
2375
+ y: (ym + yp) / 2,
2376
+ x: xp,
2377
+ z: zm
2378
+ });
2379
+ }
2380
+ if (isValidEdge(ret.right, ret.back)) {
2381
+ yEdges.push({
2382
+ y: (ym + yp) / 2,
2383
+ x: xp,
2384
+ z: zp
2385
+ });
2386
+ }
2387
+
2388
+ var xBottomEdges = [];
2389
+ if (isValidEdge(ret.bottom, ret.front)) {
2390
+ xBottomEdges.push({
2391
+ x: (xm + xp) / 2,
2392
+ y: yp,
2393
+ z: zm
2394
+ });
2395
+ }
2396
+ if (isValidEdge(ret.bottom, ret.back)) {
2397
+ xBottomEdges.push({
2398
+ x: (xm + xp) / 2,
2399
+ y: yp,
2400
+ z: zp
2401
+ });
2402
+ }
2403
+
2404
+ var xTopEdges = [];
2405
+ if (isValidEdge(ret.top, ret.front)) {
2406
+ xTopEdges.push({
2407
+ x: (xm + xp) / 2,
2408
+ y: ym,
2409
+ z: zm
2410
+ });
2411
+ }
2412
+ if (isValidEdge(ret.top, ret.back)) {
2413
+ xTopEdges.push({
2414
+ x: (xm + xp) / 2,
2415
+ y: ym,
2416
+ z: zp
2417
+ });
2418
+ }
2419
+
2420
+ var zBottomEdges = [];
2421
+ if (isValidEdge(ret.bottom, ret.left)) {
2422
+ zBottomEdges.push({
2423
+ z: (zm + zp) / 2,
2424
+ y: yp,
2425
+ x: xm
2426
+ });
2427
+ }
2428
+ if (isValidEdge(ret.bottom, ret.right)) {
2429
+ zBottomEdges.push({
2430
+ z: (zm + zp) / 2,
2431
+ y: yp,
2432
+ x: xp
2433
+ });
2434
+ }
2435
+
2436
+ var zTopEdges = [];
2437
+ if (isValidEdge(ret.top, ret.left)) {
2438
+ zTopEdges.push({
2439
+ z: (zm + zp) / 2,
2440
+ y: ym,
2441
+ x: xm
2442
+ });
2443
+ }
2444
+ if (isValidEdge(ret.top, ret.right)) {
2445
+ zTopEdges.push({
2446
+ z: (zm + zp) / 2,
2447
+ y: ym,
2448
+ x: xp
2449
+ });
2450
+ }
2451
+
2452
+ var pickEdge = function(edges, axis, mult) {
2453
+ if (edges.length === 0) {
2454
+ return null;
2455
+ } else if (edges.length === 1) {
2456
+ return edges[0];
2457
+ }
2458
+ var best = 0,
2459
+ projections = perspective(edges, chart, false);
2460
+ for (var i = 1; i < projections.length; i++) {
2461
+ if (mult * projections[i][axis] > mult * projections[best][axis]) {
2462
+ best = i;
2463
+ } else if ((mult * projections[i][axis] === mult * projections[best][axis]) && (projections[i].z < projections[best].z)) {
2464
+ best = i;
2465
+ }
2466
+ }
2467
+ return edges[best];
2468
+ };
2469
+ ret.axes = {
2470
+ y: {
2471
+ 'left': pickEdge(yEdges, 'x', -1),
2472
+ 'right': pickEdge(yEdges, 'x', +1)
2473
+ },
2474
+ x: {
2475
+ 'top': pickEdge(xTopEdges, 'y', -1),
2476
+ 'bottom': pickEdge(xBottomEdges, 'y', +1)
2477
+ },
2478
+ z: {
2479
+ 'top': pickEdge(zTopEdges, 'y', -1),
2480
+ 'bottom': pickEdge(zBottomEdges, 'y', +1)
2481
+ }
2482
+ };
2483
+ } else {
2484
+ ret.axes = {
2485
+ y: {
2486
+ 'left': {
2487
+ x: xm,
2488
+ z: zm
2489
+ },
2490
+ 'right': {
2491
+ x: xp,
2492
+ z: zm
2493
+ }
2494
+ },
2495
+ x: {
2496
+ 'top': {
2497
+ y: ym,
2498
+ z: zm
2499
+ },
2500
+ 'bottom': {
2501
+ y: yp,
2502
+ z: zm
2503
+ }
2504
+ },
2505
+ z: {
2506
+ 'top': {
2507
+ x: defaultShowLeft ? xp : xm,
2508
+ y: ym
2509
+ },
2510
+ 'bottom': {
2511
+ x: defaultShowLeft ? xp : xm,
2512
+ y: yp
2513
+ }
2514
+ }
2515
+ };
2516
+ }
2517
+
2518
+ return ret;
2519
+ };
2520
+
2521
+
1152
2522
  }(Highcharts));
1153
2523
  (function(H) {
1154
2524
  /**
@@ -1181,109 +2551,6 @@
1181
2551
  }
1182
2552
  });
1183
2553
 
1184
- wrap(Axis.prototype, 'render', function(proceed) {
1185
- proceed.apply(this, [].slice.call(arguments, 1));
1186
-
1187
- // Do not do this if the chart is not 3D
1188
- if (!this.chart.is3d() || this.coll === 'colorAxis') {
1189
- return;
1190
- }
1191
-
1192
- var chart = this.chart,
1193
- renderer = chart.renderer,
1194
- options3d = chart.options.chart.options3d,
1195
- frame = options3d.frame,
1196
- fbottom = frame.bottom,
1197
- fback = frame.back,
1198
- fside = frame.side,
1199
- depth = options3d.depth,
1200
- height = this.height,
1201
- width = this.width,
1202
- left = this.left,
1203
- top = this.top;
1204
-
1205
- if (this.isZAxis) {
1206
- return;
1207
- }
1208
- if (this.horiz) {
1209
- var bottomShape = {
1210
- x: left,
1211
- y: top + (chart.xAxis[0].opposite ? -fbottom.size : height),
1212
- z: 0,
1213
- width: width,
1214
- height: fbottom.size,
1215
- depth: depth,
1216
- insidePlotArea: false
1217
- };
1218
- if (!this.bottomFrame) {
1219
- this.bottomFrame = renderer.cuboid(bottomShape).attr({
1220
- 'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
1221
- 'zIndex': (chart.yAxis[0].reversed && options3d.alpha > 0 ? 4 : -1)
1222
- }).add();
1223
-
1224
-
1225
- this.bottomFrame.attr({
1226
- fill: fbottom.color || 'none',
1227
- stroke: fbottom.color || 'none'
1228
- });
1229
-
1230
- } else {
1231
- this.bottomFrame.animate(bottomShape);
1232
- }
1233
- } else {
1234
- // BACK
1235
- var backShape = {
1236
- x: left + (chart.yAxis[0].opposite ? 0 : -fside.size),
1237
- y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
1238
- z: depth,
1239
- width: width + fside.size,
1240
- height: height + fbottom.size,
1241
- depth: fback.size,
1242
- insidePlotArea: false
1243
- };
1244
- if (!this.backFrame) {
1245
- this.backFrame = renderer.cuboid(backShape).attr({
1246
- 'class': 'highcharts-3d-frame highcharts-3d-frame-back',
1247
- zIndex: -3
1248
- }).add();
1249
-
1250
-
1251
- this.backFrame.attr({
1252
- fill: fback.color || 'none',
1253
- stroke: fback.color || 'none'
1254
- });
1255
-
1256
- } else {
1257
- this.backFrame.animate(backShape);
1258
- }
1259
- var sideShape = {
1260
- x: left + (chart.yAxis[0].opposite ? width : -fside.size),
1261
- y: top + (chart.xAxis[0].opposite ? -fbottom.size : 0),
1262
- z: 0,
1263
- width: fside.size,
1264
- height: height + fbottom.size,
1265
- depth: depth,
1266
- insidePlotArea: false
1267
- };
1268
- if (!this.sideFrame) {
1269
- this.sideFrame = renderer.cuboid(sideShape).attr({
1270
- 'class': 'highcharts-3d-frame highcharts-3d-frame-side',
1271
- zIndex: -2
1272
- }).add();
1273
-
1274
-
1275
- this.sideFrame.attr({
1276
- fill: fside.color || 'none',
1277
- stroke: fside.color || 'none'
1278
- });
1279
-
1280
-
1281
- } else {
1282
- this.sideFrame.animate(sideShape);
1283
- }
1284
- }
1285
- });
1286
-
1287
2554
  wrap(Axis.prototype, 'getPlotLinePath', function(proceed) {
1288
2555
  var path = proceed.apply(this, [].slice.call(arguments, 1));
1289
2556
 
@@ -1299,15 +2566,13 @@
1299
2566
  var chart = this.chart,
1300
2567
  options3d = chart.options.chart.options3d,
1301
2568
  d = this.isZAxis ? chart.plotWidth : options3d.depth,
1302
- opposite = this.opposite;
1303
- if (this.horiz) {
1304
- opposite = !opposite;
1305
- }
2569
+ frame = chart.frame3d;
2570
+
1306
2571
  var pArr = [
1307
2572
  this.swapZ({
1308
2573
  x: path[1],
1309
2574
  y: path[2],
1310
- z: (opposite ? d : 0)
2575
+ z: 0
1311
2576
  }),
1312
2577
  this.swapZ({
1313
2578
  x: path[1],
@@ -1317,19 +2582,60 @@
1317
2582
  this.swapZ({
1318
2583
  x: path[4],
1319
2584
  y: path[5],
1320
- z: d
2585
+ z: 0
1321
2586
  }),
1322
2587
  this.swapZ({
1323
2588
  x: path[4],
1324
2589
  y: path[5],
1325
- z: (opposite ? 0 : d)
2590
+ z: d
1326
2591
  })
1327
2592
  ];
1328
2593
 
1329
- pArr = perspective(pArr, this.chart, false);
1330
- path = this.chart.renderer.toLinePath(pArr, false);
2594
+ var pathSegments = [];
2595
+ if (!this.horiz) { // Y-Axis
2596
+ if (frame.front.visible) {
2597
+ pathSegments.push(pArr[0], pArr[2]);
2598
+ }
2599
+ if (frame.back.visible) {
2600
+ pathSegments.push(pArr[1], pArr[3]);
2601
+ }
2602
+ if (frame.left.visible) {
2603
+ pathSegments.push(pArr[0], pArr[1]);
2604
+ }
2605
+ if (frame.right.visible) {
2606
+ pathSegments.push(pArr[2], pArr[3]);
2607
+ }
2608
+ } else if (this.isZAxis) { // Z-Axis
2609
+ if (frame.left.visible) {
2610
+ pathSegments.push(pArr[0], pArr[2]);
2611
+ }
2612
+ if (frame.right.visible) {
2613
+ pathSegments.push(pArr[1], pArr[3]);
2614
+ }
2615
+ if (frame.top.visible) {
2616
+ pathSegments.push(pArr[0], pArr[1]);
2617
+ }
2618
+ if (frame.bottom.visible) {
2619
+ pathSegments.push(pArr[2], pArr[3]);
2620
+ }
2621
+ } else { // X-Axis
2622
+ if (frame.front.visible) {
2623
+ pathSegments.push(pArr[0], pArr[2]);
2624
+ }
2625
+ if (frame.back.visible) {
2626
+ pathSegments.push(pArr[1], pArr[3]);
2627
+ }
2628
+ if (frame.top.visible) {
2629
+ pathSegments.push(pArr[0], pArr[1]);
2630
+ }
2631
+ if (frame.bottom.visible) {
2632
+ pathSegments.push(pArr[2], pArr[3]);
2633
+ }
2634
+ }
2635
+
2636
+ pathSegments = perspective(pathSegments, this.chart, false);
1331
2637
 
1332
- return path;
2638
+ return this.chart.renderer.toLineSegments(pathSegments);
1333
2639
  });
1334
2640
 
1335
2641
  // Do not draw axislines in 3D
@@ -1346,31 +2652,99 @@
1346
2652
  var args = arguments,
1347
2653
  from = args[1],
1348
2654
  to = args[2],
1349
- toPath = this.getPlotLinePath(to),
1350
- path = this.getPlotLinePath(from);
1351
-
1352
- if (path && toPath) {
1353
- path.push(
1354
- 'L',
1355
- toPath[10], // These two do not exist in the regular getPlotLine
1356
- toPath[11], // ---- # 3005
1357
- 'L',
1358
- toPath[7],
1359
- toPath[8],
1360
- 'L',
1361
- toPath[4],
1362
- toPath[5],
1363
- 'L',
1364
- toPath[1],
1365
- toPath[2]
1366
- );
1367
- } else { // outside the axis area
1368
- path = null;
2655
+ path = [],
2656
+ fromPath = this.getPlotLinePath(from),
2657
+ toPath = this.getPlotLinePath(to);
2658
+
2659
+ if (fromPath && toPath) {
2660
+ for (var i = 0; i < fromPath.length; i += 6) {
2661
+ path.push(
2662
+ 'M', fromPath[i + 1], fromPath[i + 2],
2663
+ 'L', fromPath[i + 4], fromPath[i + 5],
2664
+ 'L', toPath[i + 4], toPath[i + 5],
2665
+ 'L', toPath[i + 1], toPath[i + 2],
2666
+ 'Z');
2667
+ }
1369
2668
  }
1370
2669
 
1371
2670
  return path;
1372
2671
  });
1373
2672
 
2673
+
2674
+ function fix3dPosition(axis, pos) {
2675
+ if (axis.chart.is3d() && axis.coll !== 'colorAxis') {
2676
+ var chart = axis.chart,
2677
+ frame = chart.frame3d,
2678
+ plotLeft = chart.plotLeft,
2679
+ plotRight = chart.plotWidth + plotLeft,
2680
+ plotTop = chart.plotTop,
2681
+ plotBottom = chart.plotHeight + plotTop,
2682
+ dx = 0,
2683
+ dy = 0;
2684
+
2685
+ pos = axis.swapZ({
2686
+ x: pos.x,
2687
+ y: pos.y,
2688
+ z: 0
2689
+ });
2690
+
2691
+
2692
+ if (axis.isZAxis) { // Z Axis
2693
+ if (axis.opposite) {
2694
+ if (frame.axes.z.top === null) {
2695
+ return {};
2696
+ }
2697
+ dy = pos.y - plotTop;
2698
+ pos.x = frame.axes.z.top.x;
2699
+ pos.y = frame.axes.z.top.y;
2700
+ } else {
2701
+ if (frame.axes.z.bottom === null) {
2702
+ return {};
2703
+ }
2704
+ dy = pos.y - plotBottom;
2705
+ pos.x = frame.axes.z.bottom.x;
2706
+ pos.y = frame.axes.z.bottom.y;
2707
+ }
2708
+ } else if (axis.horiz) { // X Axis
2709
+ if (axis.opposite) {
2710
+ if (frame.axes.x.top === null) {
2711
+ return {};
2712
+ }
2713
+ dy = pos.y - plotTop;
2714
+ pos.y = frame.axes.x.top.y;
2715
+ pos.z = frame.axes.x.top.z;
2716
+ } else {
2717
+ if (frame.axes.x.bottom === null) {
2718
+ return {};
2719
+ }
2720
+ dy = pos.y - plotBottom;
2721
+ pos.y = frame.axes.x.bottom.y;
2722
+ pos.z = frame.axes.x.bottom.z;
2723
+ }
2724
+ } else { //Y Axis
2725
+ if (axis.opposite) {
2726
+ if (frame.axes.y.right === null) {
2727
+ return {};
2728
+ }
2729
+ dx = pos.x - plotRight;
2730
+ pos.x = frame.axes.y.right.x;
2731
+ pos.z = frame.axes.y.right.z;
2732
+ } else {
2733
+ if (frame.axes.y.left === null) {
2734
+ return {};
2735
+ }
2736
+ dx = pos.x - plotLeft;
2737
+ pos.x = frame.axes.y.left.x;
2738
+ pos.z = frame.axes.y.left.z;
2739
+ }
2740
+ }
2741
+ pos = perspective([pos], axis.chart)[0];
2742
+ pos.x += dx;
2743
+ pos.y += dy;
2744
+ }
2745
+ return pos;
2746
+ }
2747
+
1374
2748
  /***
1375
2749
  EXTENSION TO THE TICKS
1376
2750
  ***/
@@ -1378,73 +2752,30 @@
1378
2752
  wrap(Tick.prototype, 'getMarkPath', function(proceed) {
1379
2753
  var path = proceed.apply(this, [].slice.call(arguments, 1));
1380
2754
 
1381
- // Do not do this if the chart is not 3D
1382
- if (!this.axis.chart.is3d() || this.axis.coll === 'colorAxis') {
1383
- return path;
1384
- }
1385
-
1386
2755
  var pArr = [
1387
- this.axis.swapZ({
2756
+ fix3dPosition(this.axis, {
1388
2757
  x: path[1],
1389
2758
  y: path[2],
1390
2759
  z: 0
1391
2760
  }),
1392
- this.axis.swapZ({
2761
+ fix3dPosition(this.axis, {
1393
2762
  x: path[4],
1394
2763
  y: path[5],
1395
2764
  z: 0
1396
2765
  })
1397
2766
  ];
1398
2767
 
1399
- pArr = perspective(pArr, this.axis.chart, false);
1400
- path = [
1401
- 'M', pArr[0].x, pArr[0].y,
1402
- 'L', pArr[1].x, pArr[1].y
1403
- ];
1404
- return path;
2768
+ return this.axis.chart.renderer.toLineSegments(pArr);
1405
2769
  });
1406
2770
 
1407
2771
  wrap(Tick.prototype, 'getLabelPosition', function(proceed) {
1408
2772
  var pos = proceed.apply(this, [].slice.call(arguments, 1));
1409
-
1410
- // Do not do this if the chart is not 3D
1411
- if (this.axis.chart.is3d() && this.axis.coll !== 'colorAxis') {
1412
- pos = perspective([this.axis.swapZ({
1413
- x: pos.x,
1414
- y: pos.y,
1415
- z: 0
1416
- })], this.axis.chart, false)[0];
1417
- }
1418
- return pos;
2773
+ return fix3dPosition(this.axis, pos);
1419
2774
  });
1420
2775
 
1421
2776
  H.wrap(Axis.prototype, 'getTitlePosition', function(proceed) {
1422
- var is3d = this.chart.is3d() && this.coll !== 'colorAxis',
1423
- pos,
1424
- axisTitleMargin;
1425
-
1426
- // Pull out the axis title margin, that is not subject to the perspective
1427
- if (is3d) {
1428
- axisTitleMargin = this.axisTitleMargin;
1429
- this.axisTitleMargin = 0;
1430
- }
1431
-
1432
- pos = proceed.apply(this, [].slice.call(arguments, 1));
1433
-
1434
- if (is3d) {
1435
- pos = perspective([this.swapZ({
1436
- x: pos.x,
1437
- y: pos.y,
1438
- z: 0
1439
- })], this.chart, false)[0];
1440
-
1441
- // Re-apply the axis title margin outside the perspective
1442
- pos[this.horiz ? 'y' : 'x'] += (this.horiz ? 1 : -1) * // horizontal axis reverses the margin ...
1443
- (this.opposite ? -1 : 1) * // ... so does opposite axes
1444
- axisTitleMargin;
1445
- this.axisTitleMargin = axisTitleMargin;
1446
- }
1447
- return pos;
2777
+ var pos = proceed.apply(this, [].slice.call(arguments, 1));
2778
+ return fix3dPosition(this, pos);
1448
2779
  });
1449
2780
 
1450
2781
  wrap(Axis.prototype, 'drawCrosshair', function(proceed) {
@@ -1476,9 +2807,8 @@
1476
2807
  Axis.prototype.swapZ = function(p, insidePlotArea) {
1477
2808
  if (this.isZAxis) {
1478
2809
  var plotLeft = insidePlotArea ? 0 : this.chart.plotLeft;
1479
- var chart = this.chart;
1480
2810
  return {
1481
- x: plotLeft + (chart.yAxis[0].opposite ? p.z : chart.xAxis[0].width - p.z),
2811
+ x: plotLeft + p.z,
1482
2812
  y: p.y,
1483
2813
  z: p.x - plotLeft
1484
2814
  };
@@ -2203,10 +3533,13 @@
2203
3533
  animate: false
2204
3534
  });
2205
3535
 
3536
+ VMLRenderer.prototype.face3d = SVGRenderer.prototype.face3d;
3537
+ VMLRenderer.prototype.polyhedron = SVGRenderer.prototype.polyhedron;
2206
3538
  VMLRenderer.prototype.cuboid = SVGRenderer.prototype.cuboid;
2207
3539
  VMLRenderer.prototype.cuboidPath = SVGRenderer.prototype.cuboidPath;
2208
3540
 
2209
3541
  VMLRenderer.prototype.toLinePath = SVGRenderer.prototype.toLinePath;
3542
+ VMLRenderer.prototype.toLineSegments = SVGRenderer.prototype.toLineSegments;
2210
3543
 
2211
3544
  VMLRenderer.prototype.createElement3D = SVGRenderer.prototype.createElement3D;
2212
3545