1578 lines
54 KiB
JavaScript
1578 lines
54 KiB
JavaScript
/* *
|
|
*
|
|
* (c) 2010-2020 Torstein Honsi
|
|
*
|
|
* Extension for 3D charts
|
|
*
|
|
* License: www.highcharts.com/license
|
|
*
|
|
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
|
*
|
|
* */
|
|
'use strict';
|
|
import Axis from '../parts/Axis.js';
|
|
import Axis3D from './Axis3D.js';
|
|
import H from '../parts/Globals.js';
|
|
import U from '../parts/Utilities.js';
|
|
var addEvent = U.addEvent, Fx = U.Fx, isArray = U.isArray, merge = U.merge, pick = U.pick, wrap = U.wrap;
|
|
import ZAxis from './ZAxis.js';
|
|
import '../parts/Chart.js';
|
|
var Chart = H.Chart, perspective = H.perspective;
|
|
/**
|
|
* Shorthand to check the is3d flag.
|
|
* @private
|
|
* @return {boolean}
|
|
* Whether it is a 3D chart.
|
|
*/
|
|
Chart.prototype.is3d = function () {
|
|
return (this.options.chart.options3d &&
|
|
this.options.chart.options3d.enabled); // #4280
|
|
};
|
|
Chart.prototype.propsRequireDirtyBox.push('chart.options3d');
|
|
Chart.prototype.propsRequireUpdateSeries.push('chart.options3d');
|
|
/* eslint-disable no-invalid-this */
|
|
// Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to the
|
|
// real 'scatter3d' series type.
|
|
addEvent(Chart, 'afterInit', function () {
|
|
var options = this.options;
|
|
if (this.is3d()) {
|
|
(options.series || []).forEach(function (s) {
|
|
var type = s.type ||
|
|
options.chart.type ||
|
|
options.chart.defaultSeriesType;
|
|
if (type === 'scatter') {
|
|
s.type = 'scatter3d';
|
|
}
|
|
});
|
|
}
|
|
});
|
|
// And do it on dynamic add (#8407)
|
|
addEvent(Chart, 'addSeries', function (e) {
|
|
if (this.is3d()) {
|
|
if (e.options.type === 'scatter') {
|
|
e.options.type = 'scatter3d';
|
|
}
|
|
}
|
|
});
|
|
/**
|
|
* Calculate scale of the 3D view. That is required to
|
|
* fit chart's 3D projection into the actual plotting area. Reported as #4933.
|
|
* @notice This function should ideally take the plot values instead of a chart
|
|
* object, but since the chart object is needed for perspective it is
|
|
* not practical. Possible to make both getScale and perspective more
|
|
* logical and also immutable.
|
|
*
|
|
* @private
|
|
* @function getScale
|
|
*
|
|
* @param {Highcharts.Chart} chart
|
|
* Chart object
|
|
*
|
|
* @param {number} depth
|
|
* The depth of the chart
|
|
*
|
|
* @return {number}
|
|
* The scale to fit the 3D chart into the plotting area.
|
|
*
|
|
* @requires highcharts-3d
|
|
*/
|
|
function getScale(chart, depth) {
|
|
var plotLeft = chart.plotLeft, plotRight = chart.plotWidth + plotLeft, plotTop = chart.plotTop, plotBottom = chart.plotHeight + plotTop, originX = plotLeft + chart.plotWidth / 2, originY = plotTop + chart.plotHeight / 2, bbox3d = {
|
|
minX: Number.MAX_VALUE,
|
|
maxX: -Number.MAX_VALUE,
|
|
minY: Number.MAX_VALUE,
|
|
maxY: -Number.MAX_VALUE
|
|
}, corners, scale = 1;
|
|
// Top left corners:
|
|
corners = [{
|
|
x: plotLeft,
|
|
y: plotTop,
|
|
z: 0
|
|
}, {
|
|
x: plotLeft,
|
|
y: plotTop,
|
|
z: depth
|
|
}];
|
|
// Top right corners:
|
|
[0, 1].forEach(function (i) {
|
|
corners.push({
|
|
x: plotRight,
|
|
y: corners[i].y,
|
|
z: corners[i].z
|
|
});
|
|
});
|
|
// All bottom corners:
|
|
[0, 1, 2, 3].forEach(function (i) {
|
|
corners.push({
|
|
x: corners[i].x,
|
|
y: plotBottom,
|
|
z: corners[i].z
|
|
});
|
|
});
|
|
// Calculate 3D corners:
|
|
corners = perspective(corners, chart, false);
|
|
// Get bounding box of 3D element:
|
|
corners.forEach(function (corner) {
|
|
bbox3d.minX = Math.min(bbox3d.minX, corner.x);
|
|
bbox3d.maxX = Math.max(bbox3d.maxX, corner.x);
|
|
bbox3d.minY = Math.min(bbox3d.minY, corner.y);
|
|
bbox3d.maxY = Math.max(bbox3d.maxY, corner.y);
|
|
});
|
|
// Left edge:
|
|
if (plotLeft > bbox3d.minX) {
|
|
scale = Math.min(scale, 1 - Math.abs((plotLeft + originX) / (bbox3d.minX + originX)) % 1);
|
|
}
|
|
// Right edge:
|
|
if (plotRight < bbox3d.maxX) {
|
|
scale = Math.min(scale, (plotRight - originX) / (bbox3d.maxX - originX));
|
|
}
|
|
// Top edge:
|
|
if (plotTop > bbox3d.minY) {
|
|
if (bbox3d.minY < 0) {
|
|
scale = Math.min(scale, (plotTop + originY) / (-bbox3d.minY + plotTop + originY));
|
|
}
|
|
else {
|
|
scale = Math.min(scale, 1 - (plotTop + originY) / (bbox3d.minY + originY) % 1);
|
|
}
|
|
}
|
|
// Bottom edge:
|
|
if (plotBottom < bbox3d.maxY) {
|
|
scale = Math.min(scale, Math.abs((plotBottom - originY) / (bbox3d.maxY - originY)));
|
|
}
|
|
return scale;
|
|
}
|
|
wrap(H.Chart.prototype, 'isInsidePlot', function (proceed) {
|
|
return this.is3d() || proceed.apply(this, [].slice.call(arguments, 1));
|
|
});
|
|
var defaultOptions = H.getOptions();
|
|
/**
|
|
* @optionparent
|
|
*/
|
|
var extendedOptions = {
|
|
chart: {
|
|
/**
|
|
* Options to render charts in 3 dimensions. This feature requires
|
|
* `highcharts-3d.js`, found in the download package or online at
|
|
* [code.highcharts.com/highcharts-3d.js](https://code.highcharts.com/highcharts-3d.js).
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @requires highcharts-3d
|
|
*/
|
|
options3d: {
|
|
/**
|
|
* Wether to render the chart using the 3D functionality.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
*/
|
|
enabled: false,
|
|
/**
|
|
* One of the two rotation angles for the chart.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
*/
|
|
alpha: 0,
|
|
/**
|
|
* One of the two rotation angles for the chart.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
*/
|
|
beta: 0,
|
|
/**
|
|
* The total depth of the chart.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
*/
|
|
depth: 100,
|
|
/**
|
|
* Whether the 3d box should automatically adjust to the chart plot
|
|
* area.
|
|
*
|
|
* @since 4.2.4
|
|
* @product highcharts
|
|
*/
|
|
fitToPlot: true,
|
|
/**
|
|
* Defines the distance the viewer is standing in front of the
|
|
* chart, this setting is important to calculate the perspective
|
|
* effect in column and scatter charts. It is not used for 3D pie
|
|
* charts.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
*/
|
|
viewDistance: 25,
|
|
/**
|
|
* Set it to `"auto"` to automatically move the labels to the best
|
|
* edge.
|
|
*
|
|
* @type {"auto"|null}
|
|
* @since 5.0.12
|
|
* @product highcharts
|
|
*/
|
|
axisLabelPosition: null,
|
|
/**
|
|
* Provides the option to draw a frame around the charts by defining
|
|
* a bottom, front and back panel.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @requires highcharts-3d
|
|
*/
|
|
frame: {
|
|
/**
|
|
* Whether the frames are visible.
|
|
*/
|
|
visible: 'default',
|
|
/**
|
|
* General pixel thickness for the frame faces.
|
|
*/
|
|
size: 1,
|
|
/**
|
|
* The bottom of the frame around a 3D chart.
|
|
*
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @requires highcharts-3d
|
|
*/
|
|
/**
|
|
* The color of the panel.
|
|
*
|
|
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
|
* @default transparent
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @apioption chart.options3d.frame.bottom.color
|
|
*/
|
|
/**
|
|
* The thickness of the panel.
|
|
*
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @apioption chart.options3d.frame.bottom.size
|
|
*/
|
|
/**
|
|
* Whether to display the frame. Possible values are `true`,
|
|
* `false`, `"auto"` to display only the frames behind the data,
|
|
* and `"default"` to display faces behind the data based on the
|
|
* axis layout, ignoring the point of view.
|
|
*
|
|
* @sample {highcharts} highcharts/3d/scatter-frame/
|
|
* Auto frames
|
|
*
|
|
* @type {boolean|"default"|"auto"}
|
|
* @default default
|
|
* @since 5.0.12
|
|
* @product highcharts
|
|
* @apioption chart.options3d.frame.bottom.visible
|
|
*/
|
|
/**
|
|
* The bottom of the frame around a 3D chart.
|
|
*/
|
|
bottom: {},
|
|
/**
|
|
* The top of the frame around a 3D chart.
|
|
*
|
|
* @extends chart.options3d.frame.bottom
|
|
*/
|
|
top: {},
|
|
/**
|
|
* The left side of the frame around a 3D chart.
|
|
*
|
|
* @extends chart.options3d.frame.bottom
|
|
*/
|
|
left: {},
|
|
/**
|
|
* The right of the frame around a 3D chart.
|
|
*
|
|
* @extends chart.options3d.frame.bottom
|
|
*/
|
|
right: {},
|
|
/**
|
|
* The back side of the frame around a 3D chart.
|
|
*
|
|
* @extends chart.options3d.frame.bottom
|
|
*/
|
|
back: {},
|
|
/**
|
|
* The front of the frame around a 3D chart.
|
|
*
|
|
* @extends chart.options3d.frame.bottom
|
|
*/
|
|
front: {}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
merge(true, defaultOptions, extendedOptions);
|
|
// Add the required CSS classes for column sides (#6018)
|
|
addEvent(Chart, 'afterGetContainer', function () {
|
|
if (this.styledMode) {
|
|
this.renderer.definition({
|
|
tagName: 'style',
|
|
textContent: '.highcharts-3d-top{' +
|
|
'filter: url(#highcharts-brighter)' +
|
|
'}\n' +
|
|
'.highcharts-3d-side{' +
|
|
'filter: url(#highcharts-darker)' +
|
|
'}\n'
|
|
});
|
|
// Add add definitions used by brighter and darker faces of the cuboids.
|
|
[{
|
|
name: 'darker',
|
|
slope: 0.6
|
|
}, {
|
|
name: 'brighter',
|
|
slope: 1.4
|
|
}].forEach(function (cfg) {
|
|
this.renderer.definition({
|
|
tagName: 'filter',
|
|
id: 'highcharts-' + cfg.name,
|
|
children: [{
|
|
tagName: 'feComponentTransfer',
|
|
children: [{
|
|
tagName: 'feFuncR',
|
|
type: 'linear',
|
|
slope: cfg.slope
|
|
}, {
|
|
tagName: 'feFuncG',
|
|
type: 'linear',
|
|
slope: cfg.slope
|
|
}, {
|
|
tagName: 'feFuncB',
|
|
type: 'linear',
|
|
slope: cfg.slope
|
|
}]
|
|
}]
|
|
});
|
|
}, this);
|
|
}
|
|
});
|
|
wrap(Chart.prototype, 'setClassName', function (proceed) {
|
|
proceed.apply(this, [].slice.call(arguments, 1));
|
|
if (this.is3d()) {
|
|
this.container.className += ' highcharts-3d-chart';
|
|
}
|
|
});
|
|
addEvent(H.Chart, 'afterSetChartSize', function () {
|
|
var chart = this, options3d = chart.options.chart.options3d;
|
|
if (chart.is3d()) {
|
|
// Add a 0-360 normalisation for alfa and beta angles in 3d graph
|
|
if (options3d) {
|
|
options3d.alpha = options3d.alpha % 360 + (options3d.alpha >= 0 ? 0 : 360);
|
|
options3d.beta = options3d.beta % 360 + (options3d.beta >= 0 ? 0 : 360);
|
|
}
|
|
var inverted = chart.inverted, clipBox = chart.clipBox, margin = chart.margin, x = inverted ? 'y' : 'x', y = inverted ? 'x' : 'y', w = inverted ? 'height' : 'width', h = inverted ? 'width' : 'height';
|
|
clipBox[x] = -(margin[3] || 0);
|
|
clipBox[y] = -(margin[0] || 0);
|
|
clipBox[w] =
|
|
chart.chartWidth + (margin[3] || 0) + (margin[1] || 0);
|
|
clipBox[h] =
|
|
chart.chartHeight + (margin[0] || 0) + (margin[2] || 0);
|
|
// Set scale, used later in perspective method():
|
|
// getScale uses perspective, so scale3d has to be reset.
|
|
chart.scale3d = 1;
|
|
if (options3d.fitToPlot === true) {
|
|
chart.scale3d = getScale(chart, options3d.depth);
|
|
}
|
|
// Recalculate the 3d frame with every call of setChartSize,
|
|
// instead of doing it after every redraw(). It avoids ticks
|
|
// and axis title outside of chart.
|
|
chart.frame3d = this.get3dFrame(); // #7942
|
|
}
|
|
});
|
|
addEvent(Chart, 'beforeRedraw', function () {
|
|
if (this.is3d()) {
|
|
// Set to force a redraw of all elements
|
|
this.isDirtyBox = true;
|
|
}
|
|
});
|
|
addEvent(Chart, 'beforeRender', function () {
|
|
if (this.is3d()) {
|
|
this.frame3d = this.get3dFrame();
|
|
}
|
|
});
|
|
// Draw the series in the reverse order (#3803, #3917)
|
|
wrap(Chart.prototype, 'renderSeries', function (proceed) {
|
|
var series, i = this.series.length;
|
|
if (this.is3d()) {
|
|
while (i--) {
|
|
series = this.series[i];
|
|
series.translate();
|
|
series.render();
|
|
}
|
|
}
|
|
else {
|
|
proceed.call(this);
|
|
}
|
|
});
|
|
addEvent(Chart, 'afterDrawChartBox', function () {
|
|
if (this.is3d()) {
|
|
var chart = this, renderer = chart.renderer, options3d = this.options.chart.options3d, frame = chart.get3dFrame(), xm = this.plotLeft, xp = this.plotLeft + this.plotWidth, ym = this.plotTop, yp = this.plotTop + this.plotHeight, zm = 0, zp = options3d.depth, xmm = xm - (frame.left.visible ? frame.left.size : 0), xpp = xp + (frame.right.visible ? frame.right.size : 0), ymm = ym - (frame.top.visible ? frame.top.size : 0), ypp = yp + (frame.bottom.visible ? frame.bottom.size : 0), zmm = zm - (frame.front.visible ? frame.front.size : 0), zpp = zp + (frame.back.visible ? frame.back.size : 0), verb = chart.hasRendered ? 'animate' : 'attr';
|
|
this.frame3d = frame;
|
|
if (!this.frameShapes) {
|
|
this.frameShapes = {
|
|
bottom: renderer.polyhedron().add(),
|
|
top: renderer.polyhedron().add(),
|
|
left: renderer.polyhedron().add(),
|
|
right: renderer.polyhedron().add(),
|
|
back: renderer.polyhedron().add(),
|
|
front: renderer.polyhedron().add()
|
|
};
|
|
}
|
|
this.frameShapes.bottom[verb]({
|
|
'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
|
|
zIndex: frame.bottom.frontFacing ? -1000 : 1000,
|
|
faces: [{
|
|
fill: H.color(frame.bottom.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}],
|
|
enabled: frame.bottom.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.bottom.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.bottom.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.bottom.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.bottom.visible && !frame.left.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.bottom.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}],
|
|
enabled: frame.bottom.visible && !frame.right.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.bottom.color).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.bottom.visible && !frame.front.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.bottom.color).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}],
|
|
enabled: frame.bottom.visible && !frame.back.visible
|
|
}]
|
|
});
|
|
this.frameShapes.top[verb]({
|
|
'class': 'highcharts-3d-frame highcharts-3d-frame-top',
|
|
zIndex: frame.top.frontFacing ? -1000 : 1000,
|
|
faces: [{
|
|
fill: H.color(frame.top.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}],
|
|
enabled: frame.top.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.top.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.top.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.top.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.top.visible && !frame.left.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.top.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}],
|
|
enabled: frame.top.visible && !frame.right.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.top.color).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}],
|
|
enabled: frame.top.visible && !frame.front.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.top.color).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.top.visible && !frame.back.visible
|
|
}]
|
|
});
|
|
this.frameShapes.left[verb]({
|
|
'class': 'highcharts-3d-frame highcharts-3d-frame-left',
|
|
zIndex: frame.left.frontFacing ? -1000 : 1000,
|
|
faces: [{
|
|
fill: H.color(frame.left.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}],
|
|
enabled: frame.left.visible && !frame.bottom.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.left.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}],
|
|
enabled: frame.left.visible && !frame.top.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.left.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}],
|
|
enabled: frame.left.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.left.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}],
|
|
enabled: frame.left.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.left.color).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.left.visible && !frame.front.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.left.color).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.left.visible && !frame.back.visible
|
|
}]
|
|
});
|
|
this.frameShapes.right[verb]({
|
|
'class': 'highcharts-3d-frame highcharts-3d-frame-right',
|
|
zIndex: frame.right.frontFacing ? -1000 : 1000,
|
|
faces: [{
|
|
fill: H.color(frame.right.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}],
|
|
enabled: frame.right.visible && !frame.bottom.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.right.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}],
|
|
enabled: frame.right.visible && !frame.top.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.right.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.right.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.right.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}],
|
|
enabled: frame.right.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.right.color).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}],
|
|
enabled: frame.right.visible && !frame.front.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.right.color).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}],
|
|
enabled: frame.right.visible && !frame.back.visible
|
|
}]
|
|
});
|
|
this.frameShapes.back[verb]({
|
|
'class': 'highcharts-3d-frame highcharts-3d-frame-back',
|
|
zIndex: frame.back.frontFacing ? -1000 : 1000,
|
|
faces: [{
|
|
fill: H.color(frame.back.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}],
|
|
enabled: frame.back.visible && !frame.bottom.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.back.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.back.visible && !frame.top.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.back.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}],
|
|
enabled: frame.back.visible && !frame.left.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.back.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}],
|
|
enabled: frame.back.visible && !frame.right.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.back.color).get(),
|
|
vertexes: [{
|
|
x: xm,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zp
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zp
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zp
|
|
}],
|
|
enabled: frame.back.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.back.color).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zpp
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zpp
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zpp
|
|
}],
|
|
enabled: frame.back.visible
|
|
}]
|
|
});
|
|
this.frameShapes.front[verb]({
|
|
'class': 'highcharts-3d-frame highcharts-3d-frame-front',
|
|
zIndex: frame.front.frontFacing ? -1000 : 1000,
|
|
faces: [{
|
|
fill: H.color(frame.front.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.front.visible && !frame.bottom.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.front.color).brighten(0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}],
|
|
enabled: frame.front.visible && !frame.top.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.front.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}],
|
|
enabled: frame.front.visible && !frame.left.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.front.color).brighten(-0.1).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.front.visible && !frame.right.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.front.color).get(),
|
|
vertexes: [{
|
|
x: xp,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: ym,
|
|
z: zm
|
|
}, {
|
|
x: xm,
|
|
y: yp,
|
|
z: zm
|
|
}, {
|
|
x: xp,
|
|
y: yp,
|
|
z: zm
|
|
}],
|
|
enabled: frame.front.visible
|
|
},
|
|
{
|
|
fill: H.color(frame.front.color).get(),
|
|
vertexes: [{
|
|
x: xpp,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ypp,
|
|
z: zmm
|
|
}, {
|
|
x: xmm,
|
|
y: ymm,
|
|
z: zmm
|
|
}, {
|
|
x: xpp,
|
|
y: ymm,
|
|
z: zmm
|
|
}],
|
|
enabled: frame.front.visible
|
|
}]
|
|
});
|
|
}
|
|
});
|
|
Chart.prototype.retrieveStacks = function (stacking) {
|
|
var series = this.series, stacks = {}, stackNumber, i = 1;
|
|
this.series.forEach(function (s) {
|
|
stackNumber = pick(s.options.stack, (stacking ? 0 : series.length - 1 - s.index)); // #3841, #4532
|
|
if (!stacks[stackNumber]) {
|
|
stacks[stackNumber] = { series: [s], position: i };
|
|
i++;
|
|
}
|
|
else {
|
|
stacks[stackNumber].series.push(s);
|
|
}
|
|
});
|
|
stacks.totalStacks = i + 1;
|
|
return stacks;
|
|
};
|
|
Chart.prototype.get3dFrame = function () {
|
|
var chart = this, options3d = chart.options.chart.options3d, frameOptions = options3d.frame, xm = chart.plotLeft, xp = chart.plotLeft + chart.plotWidth, ym = chart.plotTop, yp = chart.plotTop + chart.plotHeight, zm = 0, zp = options3d.depth, faceOrientation = function (vertexes) {
|
|
var area = H.shapeArea3d(vertexes, chart);
|
|
// Give it 0.5 squared-pixel as a margin for rounding errors.
|
|
if (area > 0.5) {
|
|
return 1;
|
|
}
|
|
if (area < -0.5) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}, bottomOrientation = faceOrientation([
|
|
{ x: xm, y: yp, z: zp },
|
|
{ x: xp, y: yp, z: zp },
|
|
{ x: xp, y: yp, z: zm },
|
|
{ x: xm, y: yp, z: zm }
|
|
]), topOrientation = faceOrientation([
|
|
{ x: xm, y: ym, z: zm },
|
|
{ x: xp, y: ym, z: zm },
|
|
{ x: xp, y: ym, z: zp },
|
|
{ x: xm, y: ym, z: zp }
|
|
]), leftOrientation = faceOrientation([
|
|
{ x: xm, y: ym, z: zm },
|
|
{ x: xm, y: ym, z: zp },
|
|
{ x: xm, y: yp, z: zp },
|
|
{ x: xm, y: yp, z: zm }
|
|
]), rightOrientation = faceOrientation([
|
|
{ x: xp, y: ym, z: zp },
|
|
{ x: xp, y: ym, z: zm },
|
|
{ x: xp, y: yp, z: zm },
|
|
{ x: xp, y: yp, z: zp }
|
|
]), frontOrientation = faceOrientation([
|
|
{ x: xm, y: yp, z: zm },
|
|
{ x: xp, y: yp, z: zm },
|
|
{ x: xp, y: ym, z: zm },
|
|
{ x: xm, y: ym, z: zm }
|
|
]), backOrientation = faceOrientation([
|
|
{ x: xm, y: ym, z: zp },
|
|
{ x: xp, y: ym, z: zp },
|
|
{ x: xp, y: yp, z: zp },
|
|
{ x: xm, y: yp, z: zp }
|
|
]), defaultShowBottom = false, defaultShowTop = false, defaultShowLeft = false, defaultShowRight = false, defaultShowFront = false, defaultShowBack = true;
|
|
// The 'default' criteria to visible faces of the frame is looking up every
|
|
// axis to decide whenever the left/right//top/bottom sides of the frame
|
|
// will be shown
|
|
[]
|
|
.concat(chart.xAxis, chart.yAxis, chart.zAxis)
|
|
.forEach(function (axis) {
|
|
if (axis) {
|
|
if (axis.horiz) {
|
|
if (axis.opposite) {
|
|
defaultShowTop = true;
|
|
}
|
|
else {
|
|
defaultShowBottom = true;
|
|
}
|
|
}
|
|
else {
|
|
if (axis.opposite) {
|
|
defaultShowRight = true;
|
|
}
|
|
else {
|
|
defaultShowLeft = true;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
var getFaceOptions = function (sources, faceOrientation, defaultVisible) {
|
|
var faceAttrs = ['size', 'color', 'visible'];
|
|
var options = {};
|
|
for (var i = 0; i < faceAttrs.length; i++) {
|
|
var attr = faceAttrs[i];
|
|
for (var j = 0; j < sources.length; j++) {
|
|
if (typeof sources[j] === 'object') {
|
|
var val = sources[j][attr];
|
|
if (typeof val !== 'undefined' && val !== null) {
|
|
options[attr] = val;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var isVisible = defaultVisible;
|
|
if (options.visible === true || options.visible === false) {
|
|
isVisible = options.visible;
|
|
}
|
|
else if (options.visible === 'auto') {
|
|
isVisible = faceOrientation > 0;
|
|
}
|
|
return {
|
|
size: pick(options.size, 1),
|
|
color: pick(options.color, 'none'),
|
|
frontFacing: faceOrientation > 0,
|
|
visible: isVisible
|
|
};
|
|
};
|
|
// docs @TODO: Add all frame options (left, right, top, bottom, front, back)
|
|
// to apioptions JSDoc once the new system is up.
|
|
var ret = {
|
|
axes: {},
|
|
// FIXME: Previously, left/right, top/bottom and front/back pairs shared
|
|
// size and color.
|
|
// For compatibility and consistency sake, when one face have
|
|
// size/color/visibility set, the opposite face will default to the same
|
|
// values. Also, left/right used to be called 'side', so that's also
|
|
// added as a fallback
|
|
bottom: getFaceOptions([frameOptions.bottom, frameOptions.top, frameOptions], bottomOrientation, defaultShowBottom),
|
|
top: getFaceOptions([frameOptions.top, frameOptions.bottom, frameOptions], topOrientation, defaultShowTop),
|
|
left: getFaceOptions([
|
|
frameOptions.left,
|
|
frameOptions.right,
|
|
frameOptions.side,
|
|
frameOptions
|
|
], leftOrientation, defaultShowLeft),
|
|
right: getFaceOptions([
|
|
frameOptions.right,
|
|
frameOptions.left,
|
|
frameOptions.side,
|
|
frameOptions
|
|
], rightOrientation, defaultShowRight),
|
|
back: getFaceOptions([frameOptions.back, frameOptions.front, frameOptions], backOrientation, defaultShowBack),
|
|
front: getFaceOptions([frameOptions.front, frameOptions.back, frameOptions], frontOrientation, defaultShowFront)
|
|
};
|
|
// Decide the bast place to put axis title/labels based on the visible
|
|
// faces. Ideally, The labels can only be on the edge between a visible face
|
|
// and an invisble one. Also, the Y label should be one the left-most edge
|
|
// (right-most if opposite),
|
|
if (options3d.axisLabelPosition === 'auto') {
|
|
var isValidEdge = function (face1, face2) {
|
|
return ((face1.visible !== face2.visible) ||
|
|
(face1.visible &&
|
|
face2.visible &&
|
|
(face1.frontFacing !== face2.frontFacing)));
|
|
};
|
|
var yEdges = [];
|
|
if (isValidEdge(ret.left, ret.front)) {
|
|
yEdges.push({
|
|
y: (ym + yp) / 2,
|
|
x: xm,
|
|
z: zm,
|
|
xDir: { x: 1, y: 0, z: 0 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.left, ret.back)) {
|
|
yEdges.push({
|
|
y: (ym + yp) / 2,
|
|
x: xm,
|
|
z: zp,
|
|
xDir: { x: 0, y: 0, z: -1 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.right, ret.front)) {
|
|
yEdges.push({
|
|
y: (ym + yp) / 2,
|
|
x: xp,
|
|
z: zm,
|
|
xDir: { x: 0, y: 0, z: 1 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.right, ret.back)) {
|
|
yEdges.push({
|
|
y: (ym + yp) / 2,
|
|
x: xp,
|
|
z: zp,
|
|
xDir: { x: -1, y: 0, z: 0 }
|
|
});
|
|
}
|
|
var xBottomEdges = [];
|
|
if (isValidEdge(ret.bottom, ret.front)) {
|
|
xBottomEdges.push({
|
|
x: (xm + xp) / 2,
|
|
y: yp,
|
|
z: zm,
|
|
xDir: { x: 1, y: 0, z: 0 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.bottom, ret.back)) {
|
|
xBottomEdges.push({
|
|
x: (xm + xp) / 2,
|
|
y: yp,
|
|
z: zp,
|
|
xDir: { x: -1, y: 0, z: 0 }
|
|
});
|
|
}
|
|
var xTopEdges = [];
|
|
if (isValidEdge(ret.top, ret.front)) {
|
|
xTopEdges.push({
|
|
x: (xm + xp) / 2,
|
|
y: ym,
|
|
z: zm,
|
|
xDir: { x: 1, y: 0, z: 0 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.top, ret.back)) {
|
|
xTopEdges.push({
|
|
x: (xm + xp) / 2,
|
|
y: ym,
|
|
z: zp,
|
|
xDir: { x: -1, y: 0, z: 0 }
|
|
});
|
|
}
|
|
var zBottomEdges = [];
|
|
if (isValidEdge(ret.bottom, ret.left)) {
|
|
zBottomEdges.push({
|
|
z: (zm + zp) / 2,
|
|
y: yp,
|
|
x: xm,
|
|
xDir: { x: 0, y: 0, z: -1 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.bottom, ret.right)) {
|
|
zBottomEdges.push({
|
|
z: (zm + zp) / 2,
|
|
y: yp,
|
|
x: xp,
|
|
xDir: { x: 0, y: 0, z: 1 }
|
|
});
|
|
}
|
|
var zTopEdges = [];
|
|
if (isValidEdge(ret.top, ret.left)) {
|
|
zTopEdges.push({
|
|
z: (zm + zp) / 2,
|
|
y: ym,
|
|
x: xm,
|
|
xDir: { x: 0, y: 0, z: -1 }
|
|
});
|
|
}
|
|
if (isValidEdge(ret.top, ret.right)) {
|
|
zTopEdges.push({
|
|
z: (zm + zp) / 2,
|
|
y: ym,
|
|
x: xp,
|
|
xDir: { x: 0, y: 0, z: 1 }
|
|
});
|
|
}
|
|
var pickEdge = function (edges, axis, mult) {
|
|
if (edges.length === 0) {
|
|
return null;
|
|
}
|
|
if (edges.length === 1) {
|
|
return edges[0];
|
|
}
|
|
var best = 0, projections = perspective(edges, chart, false);
|
|
for (var i = 1; i < projections.length; i++) {
|
|
if (mult * projections[i][axis] >
|
|
mult * projections[best][axis]) {
|
|
best = i;
|
|
}
|
|
else if ((mult * projections[i][axis] ===
|
|
mult * projections[best][axis]) &&
|
|
(projections[i].z < projections[best].z)) {
|
|
best = i;
|
|
}
|
|
}
|
|
return edges[best];
|
|
};
|
|
ret.axes = {
|
|
y: {
|
|
'left': pickEdge(yEdges, 'x', -1),
|
|
'right': pickEdge(yEdges, 'x', +1)
|
|
},
|
|
x: {
|
|
'top': pickEdge(xTopEdges, 'y', -1),
|
|
'bottom': pickEdge(xBottomEdges, 'y', +1)
|
|
},
|
|
z: {
|
|
'top': pickEdge(zTopEdges, 'y', -1),
|
|
'bottom': pickEdge(zBottomEdges, 'y', +1)
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
ret.axes = {
|
|
y: {
|
|
'left': { x: xm, z: zm, xDir: { x: 1, y: 0, z: 0 } },
|
|
'right': { x: xp, z: zm, xDir: { x: 0, y: 0, z: 1 } }
|
|
},
|
|
x: {
|
|
'top': { y: ym, z: zm, xDir: { x: 1, y: 0, z: 0 } },
|
|
'bottom': { y: yp, z: zm, xDir: { x: 1, y: 0, z: 0 } }
|
|
},
|
|
z: {
|
|
'top': {
|
|
x: defaultShowLeft ? xp : xm,
|
|
y: ym,
|
|
xDir: defaultShowLeft ?
|
|
{ x: 0, y: 0, z: 1 } :
|
|
{ x: 0, y: 0, z: -1 }
|
|
},
|
|
'bottom': {
|
|
x: defaultShowLeft ? xp : xm,
|
|
y: yp,
|
|
xDir: defaultShowLeft ?
|
|
{ x: 0, y: 0, z: 1 } :
|
|
{ x: 0, y: 0, z: -1 }
|
|
}
|
|
}
|
|
};
|
|
}
|
|
return ret;
|
|
};
|
|
// Animation setter for matrix property.
|
|
Fx.prototype.matrixSetter = function () {
|
|
var interpolated;
|
|
if (this.pos < 1 &&
|
|
(isArray(this.start) || isArray(this.end))) {
|
|
var start = this.start || [1, 0, 0, 1, 0, 0];
|
|
var end = this.end || [1, 0, 0, 1, 0, 0];
|
|
interpolated = [];
|
|
for (var i = 0; i < 6; i++) {
|
|
interpolated.push(this.pos * end[i] + (1 - this.pos) * start[i]);
|
|
}
|
|
}
|
|
else {
|
|
interpolated = this.end;
|
|
}
|
|
this.elem.attr(this.prop, interpolated, null, true);
|
|
};
|
|
ZAxis.ZChartComposition.compose(Chart);
|
|
Axis3D.compose(Axis);
|
|
/**
|
|
* Note: As of v5.0.12, `frame.left` or `frame.right` should be used instead.
|
|
*
|
|
* The side for the frame around a 3D chart.
|
|
*
|
|
* @deprecated
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @requires highcharts-3d
|
|
* @apioption chart.options3d.frame.side
|
|
*/
|
|
/**
|
|
* The color of the panel.
|
|
*
|
|
* @deprecated
|
|
* @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
|
|
* @default transparent
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @apioption chart.options3d.frame.side.color
|
|
*/
|
|
/**
|
|
* The thickness of the panel.
|
|
*
|
|
* @deprecated
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 4.0
|
|
* @product highcharts
|
|
* @apioption chart.options3d.frame.side.size
|
|
*/
|
|
''; // adds doclets above to transpiled file
|