highcharts
Version:
JavaScript charting framework
1,255 lines (1,254 loc) • 65.5 kB
JavaScript
/* *
*
* (c) 2010-2021 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 '../Axis/Axis.js';
import Axis3D from '../Axis/Axis3D.js';
import Chart from './Chart.js';
import Fx from '../Animation/Fx.js';
import H from '../Globals.js';
import Math3D from '../../Extensions/Math3D.js';
var perspective = Math3D.perspective, shapeArea3D = Math3D.shapeArea3D;
import O from '../Options.js';
var genericDefaultOptions = O.defaultOptions;
import U from '../Utilities.js';
var addEvent = U.addEvent, isArray = U.isArray, merge = U.merge, pick = U.pick, wrap = U.wrap;
import ZAxis from '../Axis/ZAxis.js';
var Chart3D;
(function (Chart3D) {
/* *
*
* Interfaces
*
* */
/* *
*
* Classes
*
* */
var Composition = /** @class */ (function () {
/* *
*
* Constructors
*
* */
/**
* @private
*/
function Composition(chart) {
this.frame3d = void 0;
this.chart = chart;
}
/* *
*
* Functions
*
* */
Composition.prototype.get3dFrame = function () {
var chart = this.chart, 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 = 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;
};
/**
* 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 {number} depth
* The depth of the chart
*
* @return {number}
* The scale to fit the 3D chart into the plotting area.
*
* @requires highcharts-3d
*/
Composition.prototype.getScale = function (depth) {
var chart = this.chart, 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;
};
return Composition;
}());
Chart3D.Composition = Composition;
/* *
*
* Constants
*
* */
/**
* @optionparent
* @private
*/
Chart3D.defaultOptions = {
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: {}
}
}
}
};
/* *
*
* Functions
*
* */
/**
* @private
*/
function compose(ChartClass, FxClass) {
var chartProto = ChartClass.prototype;
var fxProto = FxClass.prototype;
/**
* Shorthand to check the is3d flag.
* @private
* @return {boolean}
* Whether it is a 3D chart.
*/
chartProto.is3d = function () {
return (this.options.chart.options3d &&
this.options.chart.options3d.enabled); // #4280
};
chartProto.propsRequireDirtyBox.push('chart.options3d');
chartProto.propsRequireUpdateSeries.push('chart.options3d');
/**
* Animation setter for matrix property.
* @private
*/
fxProto.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);
};
merge(true, genericDefaultOptions, Chart3D.defaultOptions);
addEvent(ChartClass, 'init', onInit);
addEvent(ChartClass, 'addSeries', onAddSeries);
addEvent(ChartClass, 'afterDrawChartBox', onAfterDrawChartBox);
addEvent(ChartClass, 'afterGetContainer', onAfterGetContainer);
addEvent(ChartClass, 'afterInit', onAfterInit);
addEvent(ChartClass, 'afterSetChartSize', onAfterSetChartSize);
addEvent(ChartClass, 'beforeRedraw', onBeforeRedraw);
addEvent(ChartClass, 'beforeRender', onBeforeRender);
wrap(H.Chart.prototype, 'isInsidePlot', wrapIsInsidePlot);
wrap(ChartClass, 'renderSeries', wrapRenderSeries);
wrap(ChartClass, 'setClassName', wrapSetClassName);
}
Chart3D.compose = compose;
/**
* Legacy support for HC < 6 to make 'scatter' series in a 3D chart route to
* the real 'scatter3d' series type. (#8407)
* @private
*/
function onAddSeries(e) {
if (this.is3d()) {
if (e.options.type === 'scatter') {
e.options.type = 'scatter3d';
}
}
}
/**
* @private
*/
function onAfterDrawChartBox() {
if (this.chart3d &&
this.is3d()) {
var chart = this, renderer = chart.renderer, options3d = this.options.chart.options3d, frame = this.chart3d.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.chart3d.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,