/* *
|
*
|
* (c) 2010-2019 Torstein Honsi
|
*
|
* License: www.highcharts.com/license
|
*
|
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
|
*
|
* */
|
'use strict';
|
|
var _Globals = require('../parts/Globals.js');
|
|
var _Globals2 = _interopRequireDefault(_Globals);
|
|
require('../parts/Utilities.js');
|
|
require('../parts/Series.js');
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
var addEvent = _Globals2.default.addEvent,
|
perspective = _Globals2.default.perspective,
|
pick = _Globals2.default.pick,
|
Series = _Globals2.default.Series,
|
seriesTypes = _Globals2.default.seriesTypes,
|
svg = _Globals2.default.svg,
|
wrap = _Globals2.default.wrap;
|
/**
|
* Depth of the columns in a 3D column chart. Requires `highcharts-3d.js`.
|
*
|
* @type {number}
|
* @default 25
|
* @since 4.0
|
* @product highcharts
|
* @apioption plotOptions.column.depth
|
*/
|
/**
|
* 3D columns only. The color of the edges. Similar to `borderColor`,
|
* except it defaults to the same color as the column.
|
*
|
* @type {Highcharts.ColorString}
|
* @product highcharts
|
* @apioption plotOptions.column.edgeColor
|
*/
|
/**
|
* 3D columns only. The width of the colored edges.
|
*
|
* @type {number}
|
* @default 1
|
* @product highcharts
|
* @apioption plotOptions.column.edgeWidth
|
*/
|
/**
|
* The spacing between columns on the Z Axis in a 3D chart. Requires
|
* `highcharts-3d.js`.
|
*
|
* @type {number}
|
* @default 1
|
* @since 4.0
|
* @product highcharts
|
* @apioption plotOptions.column.groupZPadding
|
*/
|
/* eslint-disable no-invalid-this */
|
wrap(seriesTypes.column.prototype, 'translate', function (proceed) {
|
proceed.apply(this, [].slice.call(arguments, 1));
|
// Do not do this if the chart is not 3D
|
if (this.chart.is3d()) {
|
this.translate3dShapes();
|
}
|
});
|
// In 3D we need to pass point.outsidePlot option to the justifyDataLabel
|
// method for disabling justifying dataLabels in columns outside plot
|
wrap(_Globals2.default.Series.prototype, 'alignDataLabel', function (proceed) {
|
arguments[3].outside3dPlot = arguments[1].outside3dPlot;
|
proceed.apply(this, [].slice.call(arguments, 1));
|
});
|
// Don't use justifyDataLabel when point is outsidePlot
|
wrap(_Globals2.default.Series.prototype, 'justifyDataLabel', function (proceed) {
|
return !arguments[2].outside3dPlot ? proceed.apply(this, [].slice.call(arguments, 1)) : false;
|
});
|
seriesTypes.column.prototype.translate3dPoints = function () {};
|
seriesTypes.column.prototype.translate3dShapes = function () {
|
var series = this,
|
chart = series.chart,
|
seriesOptions = series.options,
|
depth = seriesOptions.depth || 25,
|
stack = seriesOptions.stacking ? seriesOptions.stack || 0 : series.index,
|
// #4743
|
z = stack * (depth + (seriesOptions.groupZPadding || 1)),
|
borderCrisp = series.borderWidth % 2 ? 0.5 : 0;
|
if (chart.inverted && !series.yAxis.reversed) {
|
borderCrisp *= -1;
|
}
|
if (seriesOptions.grouping !== false) {
|
z = 0;
|
}
|
z += seriesOptions.groupZPadding || 1;
|
series.data.forEach(function (point) {
|
// #7103 Reset outside3dPlot flag
|
point.outside3dPlot = null;
|
if (point.y !== null) {
|
var shapeArgs = point.shapeArgs,
|
tooltipPos = point.tooltipPos,
|
|
// Array for final shapeArgs calculation.
|
// We are checking two dimensions (x and y).
|
dimensions = [['x', 'width'], ['y', 'height']],
|
borderlessBase; // Crisped rects can have +/- 0.5 pixels offset.
|
// #3131 We need to check if column is inside plotArea.
|
dimensions.forEach(function (d) {
|
borderlessBase = shapeArgs[d[0]] - borderCrisp;
|
if (borderlessBase < 0) {
|
// If borderLessBase is smaller than 0, it is needed to set
|
// its value to 0 or 0.5 depending on borderWidth
|
// borderWidth may be even or odd.
|
shapeArgs[d[1]] += shapeArgs[d[0]] + borderCrisp;
|
shapeArgs[d[0]] = -borderCrisp;
|
borderlessBase = 0;
|
}
|
if (borderlessBase + shapeArgs[d[1]] > series[d[0] + 'Axis'].len &&
|
// Do not change height/width of column if 0 (#6708)
|
shapeArgs[d[1]] !== 0) {
|
shapeArgs[d[1]] = series[d[0] + 'Axis'].len - shapeArgs[d[0]];
|
}
|
if (
|
// Do not remove columns with zero height/width.
|
shapeArgs[d[1]] !== 0 && (shapeArgs[d[0]] >= series[d[0] + 'Axis'].len || shapeArgs[d[0]] + shapeArgs[d[1]] <= borderCrisp)) {
|
// Set args to 0 if column is outside the chart.
|
for (var key in shapeArgs) {
|
// eslint-disable-line guard-for-in
|
shapeArgs[key] = 0;
|
}
|
// #7103 outside3dPlot flag is set on Points which are
|
// currently outside of plot.
|
point.outside3dPlot = true;
|
}
|
});
|
// Change from 2d to 3d
|
if (point.shapeType === 'rect') {
|
point.shapeType = 'cuboid';
|
}
|
shapeArgs.z = z;
|
shapeArgs.depth = depth;
|
shapeArgs.insidePlotArea = true;
|
// Translate the tooltip position in 3d space
|
tooltipPos = perspective([{
|
x: tooltipPos[0],
|
y: tooltipPos[1],
|
z: z
|
}], chart, true)[0];
|
point.tooltipPos = [tooltipPos.x, tooltipPos.y];
|
}
|
});
|
// store for later use #4067
|
series.z = z;
|
};
|
wrap(seriesTypes.column.prototype, 'animate', function (proceed) {
|
if (!this.chart.is3d()) {
|
proceed.apply(this, [].slice.call(arguments, 1));
|
} else {
|
var args = arguments,
|
init = args[1],
|
yAxis = this.yAxis,
|
series = this,
|
reversed = this.yAxis.reversed;
|
if (svg) {
|
// VML is too slow anyway
|
if (init) {
|
series.data.forEach(function (point) {
|
if (point.y !== null) {
|
point.height = point.shapeArgs.height;
|
point.shapey = point.shapeArgs.y; // #2968
|
point.shapeArgs.height = 1;
|
if (!reversed) {
|
if (point.stackY) {
|
point.shapeArgs.y = point.plotY + yAxis.translate(point.stackY);
|
} else {
|
point.shapeArgs.y = point.plotY + (point.negative ? -point.height : point.height);
|
}
|
}
|
}
|
});
|
} else {
|
// run the animation
|
series.data.forEach(function (point) {
|
if (point.y !== null) {
|
point.shapeArgs.height = point.height;
|
point.shapeArgs.y = point.shapey; // #2968
|
// null value do not have a graphic
|
if (point.graphic) {
|
point.graphic.animate(point.shapeArgs, series.options.animation);
|
}
|
}
|
});
|
// redraw datalabels to the correct position
|
this.drawDataLabels();
|
// delete this function to allow it only once
|
series.animate = null;
|
}
|
}
|
}
|
});
|
// In case of 3d columns there is no sense to add this columns to a specific
|
// series group - if series is added to a group all columns will have the same
|
// zIndex in comparison with different series.
|
wrap(seriesTypes.column.prototype, 'plotGroup', function (proceed, prop, name, visibility, zIndex, parent) {
|
if (this.chart.is3d()) {
|
if (this[prop]) {
|
delete this[prop];
|
}
|
if (parent) {
|
if (!this.chart.columnGroup) {
|
this.chart.columnGroup = this.chart.renderer.g('columnGroup').add(parent);
|
}
|
this[prop] = this.chart.columnGroup;
|
this.chart.columnGroup.attr(this.getPlotBox());
|
this[prop].survive = true;
|
if (prop === 'group' || prop === 'markerGroup') {
|
arguments[3] = 'visible';
|
// For 3D column group and markerGroup should be visible
|
}
|
}
|
}
|
return proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
});
|
// When series is not added to group it is needed to change setVisible method to
|
// allow correct Legend funcionality. This wrap is basing on pie chart series.
|
wrap(seriesTypes.column.prototype, 'setVisible', function (proceed, vis) {
|
var series = this,
|
pointVis;
|
if (series.chart.is3d()) {
|
series.data.forEach(function (point) {
|
point.visible = point.options.visible = vis = vis === undefined ? !pick(series.visible, point.visible) : vis;
|
pointVis = vis ? 'visible' : 'hidden';
|
series.options.data[series.data.indexOf(point)] = point.options;
|
if (point.graphic) {
|
point.graphic.attr({
|
visibility: pointVis
|
});
|
}
|
});
|
}
|
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
|
});
|
seriesTypes.column.prototype.handle3dGrouping = true;
|
addEvent(Series, 'afterInit', function () {
|
if (this.chart.is3d() && this.handle3dGrouping) {
|
var seriesOptions = this.options,
|
grouping = seriesOptions.grouping,
|
stacking = seriesOptions.stacking,
|
reversedStacks = pick(this.yAxis.options.reversedStacks, true),
|
z = 0;
|
if (!(grouping !== undefined && !grouping)) {
|
var stacks = this.chart.retrieveStacks(stacking),
|
stack = seriesOptions.stack || 0,
|
i; // position within the stack
|
for (i = 0; i < stacks[stack].series.length; i++) {
|
if (stacks[stack].series[i] === this) {
|
break;
|
}
|
}
|
z = 10 * (stacks.totalStacks - stacks[stack].position) + (reversedStacks ? i : -i); // #4369
|
// In case when axis is reversed, columns are also reversed inside
|
// the group (#3737)
|
if (!this.xAxis.reversed) {
|
z = stacks.totalStacks * 10 - z;
|
}
|
}
|
seriesOptions.zIndex = z;
|
}
|
});
|
// eslint-disable-next-line valid-jsdoc
|
/**
|
* @private
|
*/
|
function pointAttribs(proceed) {
|
var attr = proceed.apply(this, [].slice.call(arguments, 1));
|
if (this.chart.is3d && this.chart.is3d()) {
|
// Set the fill color to the fill color to provide a smooth edge
|
attr.stroke = this.options.edgeColor || attr.fill;
|
attr['stroke-width'] = pick(this.options.edgeWidth, 1); // #4055
|
}
|
return attr;
|
}
|
// eslint-disable-next-line valid-jsdoc
|
/**
|
* In 3D mode, all column-series are rendered in one main group. Because of that
|
* we need to apply inactive state on all points.
|
* @private
|
*/
|
function setState(proceed, state, inherit) {
|
var is3d = this.chart.is3d && this.chart.is3d();
|
if (is3d) {
|
this.options.inactiveOtherPoints = true;
|
}
|
proceed.call(this, state, inherit);
|
if (is3d) {
|
this.options.inactiveOtherPoints = false;
|
}
|
}
|
wrap(seriesTypes.column.prototype, 'pointAttribs', pointAttribs);
|
wrap(seriesTypes.column.prototype, 'setState', setState);
|
if (seriesTypes.columnrange) {
|
wrap(seriesTypes.columnrange.prototype, 'pointAttribs', pointAttribs);
|
wrap(seriesTypes.columnrange.prototype, 'setState', setState);
|
seriesTypes.columnrange.prototype.plotGroup = seriesTypes.column.prototype.plotGroup;
|
seriesTypes.columnrange.prototype.setVisible = seriesTypes.column.prototype.setVisible;
|
}
|
wrap(Series.prototype, 'alignDataLabel', function (proceed) {
|
// Only do this for 3D columns and it's derived series
|
if (this.chart.is3d() && this instanceof seriesTypes.column) {
|
var series = this,
|
chart = series.chart;
|
var args = arguments,
|
alignTo = args[4],
|
point = args[1];
|
var pos = { x: alignTo.x, y: alignTo.y, z: series.z };
|
pos = perspective([pos], chart, true)[0];
|
alignTo.x = pos.x;
|
// #7103 If point is outside of plotArea, hide data label.
|
alignTo.y = point.outside3dPlot ? -9e9 : pos.y;
|
}
|
proceed.apply(this, [].slice.call(arguments, 1));
|
});
|
// Added stackLabels position calculation for 3D charts.
|
wrap(_Globals2.default.StackItem.prototype, 'getStackBox', function (proceed, chart) {
|
var stackBox = proceed.apply(this, [].slice.call(arguments, 1));
|
// Only do this for 3D chart.
|
if (chart.is3d()) {
|
var pos = {
|
x: stackBox.x,
|
y: stackBox.y,
|
z: 0
|
};
|
pos = _Globals2.default.perspective([pos], chart, true)[0];
|
stackBox.x = pos.x;
|
stackBox.y = pos.y;
|
}
|
return stackBox;
|
});
|