highcharts
Version:
JavaScript charting framework
187 lines (186 loc) • 6.5 kB
JavaScript
/* *
*
* Highcharts variwide module
*
* (c) 2010-2024 Torstein Honsi
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
'use strict';
import SeriesRegistry from '../../Core/Series/SeriesRegistry.js';
const { column: ColumnSeries } = SeriesRegistry.seriesTypes;
import VariwideComposition from './VariwideComposition.js';
import VariwidePoint from './VariwidePoint.js';
import VariwideSeriesDefaults from './VariwideSeriesDefaults.js';
import U from '../../Core/Utilities.js';
const { addEvent, crisp, extend, merge, pick } = U;
/* *
*
* Class
*
* */
/**
* @private
* @class
* @name Highcharts.seriesTypes.variwide
*
* @augments Highcharts.Series
*/
class VariwideSeries extends ColumnSeries {
/* *
*
* Functions
*
* */
processData(force) {
this.totalZ = 0;
this.relZ = [];
SeriesRegistry.seriesTypes.column.prototype.processData.call(this, force);
const zData = this.getColumn('z');
(this.xAxis.reversed ?
zData.slice().reverse() :
zData).forEach(function (z, i) {
this.relZ[i] = this.totalZ;
this.totalZ += z;
}, this);
if (this.xAxis.categories) {
this.xAxis.variwide = true;
this.xAxis.zData = zData; // Used for label rank
}
return;
}
/**
* Translate an x value inside a given category index into the distorted
* axis translation.
*
* @private
* @function Highcharts.Series#postTranslate
*
* @param {number} index
* The category index
*
* @param {number} x
* The X pixel position in undistorted axis pixels
*
* @param {Highcharts.Point} point
* For crosshairWidth for every point
*
* @return {number}
* Distorted X position
*/
postTranslate(index, x, point) {
const axis = this.xAxis, relZ = this.relZ, i = axis.reversed ? relZ.length - index : index, goRight = axis.reversed ? -1 : 1, minPx = axis.toPixels(axis.reversed ?
(axis.dataMax || 0) + axis.pointRange :
(axis.dataMin || 0)), maxPx = axis.toPixels(axis.reversed ?
(axis.dataMin || 0) :
(axis.dataMax || 0) + axis.pointRange), len = Math.abs(maxPx - minPx), totalZ = this.totalZ, left = this.chart.inverted ?
maxPx - (this.chart.plotTop - goRight * axis.minPixelPadding) :
minPx - this.chart.plotLeft - goRight * axis.minPixelPadding, linearSlotLeft = i / relZ.length * len, linearSlotRight = (i + goRight) / relZ.length * len, slotLeft = (pick(relZ[i], totalZ) / totalZ) * len, slotRight = (pick(relZ[i + goRight], totalZ) / totalZ) * len, xInsideLinearSlot = (x - (left + linearSlotLeft));
// Set crosshairWidth for every point (#8173)
if (point) {
point.crosshairWidth = slotRight - slotLeft;
}
return left + slotLeft +
xInsideLinearSlot * (slotRight - slotLeft) /
(linearSlotRight - linearSlotLeft);
}
/* eslint-enable valid-jsdoc */
translate() {
// Temporarily disable crisping when computing original shapeArgs
this.crispOption = this.options.crisp;
this.options.crisp = false;
super.translate();
// Reset option
this.options.crisp = this.crispOption;
}
/**
* Function that corrects stack labels positions
* @private
*/
correctStackLabels() {
const series = this, options = series.options, yAxis = series.yAxis;
let pointStack, pointWidth, stack, xValue;
for (const point of series.points) {
xValue = point.x;
pointWidth = point.shapeArgs.width;
stack = yAxis.stacking.stacks[(series.negStacks &&
point.y < (options.startFromThreshold ?
0 :
options.threshold) ?
'-' :
'') + series.stackKey];
if (stack) {
pointStack = stack[xValue];
if (pointStack && !point.isNull) {
pointStack.setOffset(-(pointWidth / 2) || 0, pointWidth || 0, void 0, void 0, point.plotX, series.xAxis);
}
}
}
}
}
/* *
*
* Static Properties
*
* */
VariwideSeries.compose = VariwideComposition.compose;
VariwideSeries.defaultOptions = merge(ColumnSeries.defaultOptions, VariwideSeriesDefaults);
// Extend translation by distorting X position based on Z.
addEvent(VariwideSeries, 'afterColumnTranslate', function () {
// Temporarily disable crisping when computing original shapeArgs
const xAxis = this.xAxis, inverted = this.chart.inverted;
let i = -1;
// Distort the points to reflect z dimension
for (const point of this.points) {
++i;
const shapeArgs = point.shapeArgs || {}, { x = 0, width = 0 } = shapeArgs, { plotX = 0, tooltipPos, z = 0 } = point;
let left, right;
if (xAxis.variwide) {
left = this.postTranslate(i, x, point);
right = this.postTranslate(i, x + width);
// For linear or datetime axes, the variwide column should start with X
// and extend Z units, without modifying the axis.
}
else {
left = plotX;
right = xAxis.translate(point.x + z, false, false, false, true);
}
if (this.crispOption) {
left = crisp(left, this.borderWidth);
right = crisp(right, this.borderWidth);
}
shapeArgs.x = left;
shapeArgs.width = Math.max(right - left, 1);
// Crosshair position (#8083)
point.plotX = (left + right) / 2;
// Adjust the tooltip position
if (tooltipPos) {
if (!inverted) {
tooltipPos[0] = shapeArgs.x + shapeArgs.width / 2;
}
else {
tooltipPos[1] = xAxis.len - shapeArgs.x - shapeArgs.width / 2;
}
}
}
if (this.options.stacking) {
this.correctStackLabels();
}
}, { order: 2 });
extend(VariwideSeries.prototype, {
irregularWidths: true,
keysAffectYAxis: ['y'],
pointArrayMap: ['y', 'z'],
parallelArrays: ['x', 'y', 'z'],
pointClass: VariwidePoint
});
SeriesRegistry.registerSeriesType('variwide', VariwideSeries);
/* *
*
* Default Export
*
* */
export default VariwideSeries;