highcharts
Version:
JavaScript charting framework
1,126 lines (1,123 loc) • 217 kB
JavaScript
/**
* @license Highcharts JS v11.3.0 (2024-01-10)
*
* 3D features for Highcharts JS
*
* License: www.highcharts.com/license
*/
(function (factory) {
if (typeof module === 'object' && module.exports) {
factory['default'] = factory;
module.exports = factory;
} else if (typeof define === 'function' && define.amd) {
define('highcharts/highcharts-3d', ['highcharts'], function (Highcharts) {
factory(Highcharts);
factory.Highcharts = Highcharts;
return factory;
});
} else {
factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
}
}(function (Highcharts) {
'use strict';
var _modules = Highcharts ? Highcharts._modules : {};
function _registerModule(obj, path, args, fn) {
if (!obj.hasOwnProperty(path)) {
obj[path] = fn.apply(null, args);
if (typeof CustomEvent === 'function') {
window.dispatchEvent(new CustomEvent(
'HighchartsModuleLoaded',
{ detail: { path: path, module: obj[path] } }
));
}
}
}
_registerModule(_modules, 'Core/Math3D.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
/* *
*
* (c) 2010-2024 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { deg2rad } = H;
const { pick } = U;
/* *
*
* Functions
*
* */
/* eslint-disable max-len */
/**
* Apply 3-D rotation
* Euler Angles (XYZ):
* cosA = cos(Alfa|Roll)
* cosB = cos(Beta|Pitch)
* cosG = cos(Gamma|Yaw)
*
* Composite rotation:
* | cosB * cosG | cosB * sinG | -sinB |
* | sinA * sinB * cosG - cosA * sinG | sinA * sinB * sinG + cosA * cosG | sinA * cosB |
* | cosA * sinB * cosG + sinA * sinG | cosA * sinB * sinG - sinA * cosG | cosA * cosB |
*
* Now, Gamma/Yaw is not used (angle=0), so we assume cosG = 1 and sinG = 0, so
* we get:
* | cosB | 0 | - sinB |
* | sinA * sinB | cosA | sinA * cosB |
* | cosA * sinB | - sinA | cosA * cosB |
*
* But in browsers, y is reversed, so we get sinA => -sinA. The general result
* is:
* | cosB | 0 | - sinB | | x | | px |
* | - sinA * sinB | cosA | - sinA * cosB | x | y | = | py |
* | cosA * sinB | sinA | cosA * cosB | | z | | pz |
*
* @private
* @function rotate3D
*/
/* eslint-enable max-len */
/**
* Rotates the position as defined in angles.
* @private
* @param {number} x
* X coordinate
* @param {number} y
* Y coordinate
* @param {number} z
* Z coordinate
* @param {Highcharts.Rotation3DObject} angles
* Rotation angles
* @return {Highcharts.Position3DObject}
* Rotated position
*/
function rotate3D(x, y, z, angles) {
return {
x: angles.cosB * x - angles.sinB * z,
y: -angles.sinA * angles.sinB * x + angles.cosA * y -
angles.cosB * angles.sinA * z,
z: angles.cosA * angles.sinB * x + angles.sinA * y +
angles.cosA * angles.cosB * z
};
}
/**
* Transforms a given array of points according to the angles in chart.options.
*
* @private
* @function Highcharts.perspective
*
* @param {Array<Highcharts.Position3DObject>} points
* The array of points
*
* @param {Highcharts.Chart} chart
* The chart
*
* @param {boolean} [insidePlotArea]
* Whether to verify that the points are inside the plotArea
*
* @param {boolean} [useInvertedPersp]
* Whether to use inverted perspective in calculations
*
* @return {Array<Highcharts.Position3DObject>}
* An array of transformed points
*
* @requires highcharts-3d
*/
function perspective(points, chart, insidePlotArea, useInvertedPersp) {
const options3d = chart.options.chart.options3d,
/* The useInvertedPersp argument is used for inverted charts with
* already inverted elements, such as dataLabels or tooltip positions.
*/
inverted = pick(useInvertedPersp, insidePlotArea ? chart.inverted : false), origin = {
x: chart.plotWidth / 2,
y: chart.plotHeight / 2,
z: options3d.depth / 2,
vd: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0)
}, scale = chart.scale3d || 1, beta = deg2rad * options3d.beta * (inverted ? -1 : 1), alpha = deg2rad * options3d.alpha * (inverted ? -1 : 1), angles = {
cosA: Math.cos(alpha),
cosB: Math.cos(-beta),
sinA: Math.sin(alpha),
sinB: Math.sin(-beta)
};
if (!insidePlotArea) {
origin.x += chart.plotLeft;
origin.y += chart.plotTop;
}
// Transform each point
return points.map(function (point) {
const rotated = rotate3D((inverted ? point.y : point.x) - origin.x, (inverted ? point.x : point.y) - origin.y, (point.z || 0) - origin.z, angles),
// Apply perspective
coordinate = perspective3D(rotated, origin, origin.vd);
// Apply translation
coordinate.x = coordinate.x * scale + origin.x;
coordinate.y = coordinate.y * scale + origin.y;
coordinate.z = rotated.z * scale + origin.z;
return {
x: (inverted ? coordinate.y : coordinate.x),
y: (inverted ? coordinate.x : coordinate.y),
z: coordinate.z
};
});
}
/**
* Perspective3D function is available in global Highcharts scope because is
* needed also outside of perspective() function (#8042).
* @private
* @function Highcharts.perspective3D
*
* @param {Highcharts.Position3DObject} coordinate
* 3D position
*
* @param {Highcharts.Position3DObject} origin
* 3D root position
*
* @param {number} distance
* Perspective distance
*
* @return {Highcharts.PositionObject}
* Perspective 3D Position
*
* @requires highcharts-3d
*/
function perspective3D(coordinate, origin, distance) {
const projection = ((distance > 0) &&
(distance < Number.POSITIVE_INFINITY)) ?
distance / (coordinate.z + origin.z + distance) :
1;
return {
x: coordinate.x * projection,
y: coordinate.y * projection
};
}
/**
* Calculate a distance from camera to points - made for calculating zIndex of
* scatter points.
*
* @private
* @function Highcharts.pointCameraDistance
*
* @param {Highcharts.Dictionary<number>} coordinates
* Coordinates of the specific point
*
* @param {Highcharts.Chart} chart
* Related chart
*
* @return {number}
* Distance from camera to point
*
* @requires highcharts-3d
*/
function pointCameraDistance(coordinates, chart) {
const options3d = chart.options.chart.options3d, cameraPosition = {
x: chart.plotWidth / 2,
y: chart.plotHeight / 2,
z: pick(options3d.depth, 1) * pick(options3d.viewDistance, 0) +
options3d.depth
},
// Added support for objects with plotX or x coordinates.
distance = Math.sqrt(Math.pow(cameraPosition.x - pick(coordinates.plotX, coordinates.x), 2) +
Math.pow(cameraPosition.y - pick(coordinates.plotY, coordinates.y), 2) +
Math.pow(cameraPosition.z - pick(coordinates.plotZ, coordinates.z), 2));
return distance;
}
/**
* Calculate area of a 2D polygon using Shoelace algorithm
* https://en.wikipedia.org/wiki/Shoelace_formula
*
* @private
* @function Highcharts.shapeArea
*
* @param {Array<Highcharts.PositionObject>} vertexes
* 2D Polygon
*
* @return {number}
* Calculated area
*
* @requires highcharts-3d
*/
function shapeArea(vertexes) {
let area = 0, i, j;
for (i = 0; i < vertexes.length; i++) {
j = (i + 1) % vertexes.length;
area += vertexes[i].x * vertexes[j].y - vertexes[j].x * vertexes[i].y;
}
return area / 2;
}
/**
* Calculate area of a 3D polygon after perspective projection
*
* @private
* @function Highcharts.shapeArea3d
*
* @param {Array<Highcharts.Position3DObject>} vertexes
* 3D Polygon
*
* @param {Highcharts.Chart} chart
* Related chart
*
* @param {boolean} [insidePlotArea]
* Whether to verify that the points are inside the plotArea
*
* @return {number}
* Calculated area
*
* @requires highcharts-3d
*/
function shapeArea3D(vertexes, chart, insidePlotArea) {
return shapeArea(perspective(vertexes, chart, insidePlotArea));
}
/* *
*
* Default Export
*
* */
const Math3D = {
perspective,
perspective3D,
pointCameraDistance,
shapeArea,
shapeArea3D
};
return Math3D;
});
_registerModule(_modules, 'Core/Chart/Chart3D.js', [_modules['Core/Color/Color.js'], _modules['Core/Defaults.js'], _modules['Core/Math3D.js'], _modules['Core/Utilities.js']], function (Color, D, Math3D, U) {
/* *
*
* (c) 2010-2024 Torstein Honsi
*
* Extension for 3D charts
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
const { parse: color } = Color;
const { defaultOptions: genericDefaultOptions } = D;
const { perspective, shapeArea3D } = Math3D;
const { addEvent, isArray, merge, pick, wrap } = U;
/* *
*
* Composition
*
* */
var Chart3D;
(function (Chart3D) {
/* *
*
* Declarations
*
* */
/* *
*
* 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: {
/**
* Whether 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) {
const chartProto = ChartClass.prototype;
const 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?.enabled;
};
chartProto.propsRequireDirtyBox.push('chart.options3d');
chartProto.propsRequireUpdateSeries.push('chart.options3d');
/**
* Animation setter for matrix property.
* @private
*/
fxProto.matrixSetter = function () {
let interpolated;
if (this.pos < 1 &&
(isArray(this.start) || isArray(this.end))) {
const start = (this.start ||
[1, 0, 0, 1, 0, 0]), end = this.end || [1, 0, 0, 1, 0, 0];
interpolated = [];
for (let 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(chartProto, 'isInsidePlot', wrapIsInsidePlot);
wrap(chartProto, 'renderSeries', wrapRenderSeries);
wrap(chartProto, '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()) {
const chart = this, renderer = chart.renderer, options3d = chart.options.chart.options3d, frame = chart.chart3d.get3dFrame(), xm = chart.plotLeft, xp = chart.plotLeft + chart.plotWidth, ym = chart.plotTop, yp = chart.plotTop + chart.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';
chart.chart3d.frame3d = frame;
if (!chart.frameShapes) {
chart.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()
};
}
chart.frameShapes.bottom[verb]({
'class': 'highcharts-3d-frame highcharts-3d-frame-bottom',
zIndex: frame.bottom.frontFacing ? -1000 : 1000,
faces: [{
fill: 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: 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: 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: 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: 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: 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
}]
});
chart.frameShapes.top[verb]({
'class': 'highcharts-3d-frame highcharts-3d-frame-top',
zIndex: frame.top.frontFacing ? -1000 : 1000,
faces: [{
fill: 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: 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: 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: 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: 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: 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
}]
});
chart.frameShapes.left[verb]({
'class': 'highcharts-3d-frame highcharts-3d-frame-left',
zIndex: frame.left.frontFacing ? -1000 : 1000,
faces: [{
fill: 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: 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: 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: 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: 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: 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
}]
});
chart.frameShapes.right[verb]({
'class': 'highcharts-3d-frame highcharts-3d-frame-right',
zIndex: frame.right.frontFacing ? -1000 : 1000,
faces: [{
fill: 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: 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: 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: 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: 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: 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
}]
});
chart.frameShapes.back[verb]({
'class': 'highcharts-3d-frame highcharts-3d-frame-back',
zIndex: frame.back.frontFacing ? -1000 : 1000,
faces: [{
fill: 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: color(frame.back.color).brighten(0.1).get(),
vertexes: [{
x: xmm,
y: ymm,
z: zpp
}, {
x: xpp,
y: ymm,
z: zpp
}, {