You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
9.7 KiB
JavaScript
284 lines
9.7 KiB
JavaScript
/**
|
|
* @license Highcharts JS v6.0.4 (2017-12-15)
|
|
* Highcharts variwide module
|
|
*
|
|
* (c) 2010-2017 Torstein Honsi
|
|
*
|
|
* License: www.highcharts.com/license
|
|
*/
|
|
'use strict';
|
|
(function(factory) {
|
|
if (typeof module === 'object' && module.exports) {
|
|
module.exports = factory;
|
|
} else {
|
|
factory(Highcharts);
|
|
}
|
|
}(function(Highcharts) {
|
|
(function(H) {
|
|
/**
|
|
* Highcharts variwide module
|
|
*
|
|
* (c) 2010-2017 Torstein Honsi
|
|
*
|
|
* License: www.highcharts.com/license
|
|
*/
|
|
|
|
/**
|
|
* To do:
|
|
* - When X axis is not categorized, the scale should reflect how the z values
|
|
* increase, like a horizontal stack. But then the actual X values aren't
|
|
* reflected the the axis.. Should we introduce a Z axis too?
|
|
*/
|
|
|
|
var seriesType = H.seriesType,
|
|
seriesTypes = H.seriesTypes,
|
|
each = H.each,
|
|
pick = H.pick;
|
|
|
|
/**
|
|
* A variwide chart (related to marimekko chart) is a column chart with a
|
|
* variable width expressing a third dimension.
|
|
*
|
|
* @extends {plotOptions.column}
|
|
* @excluding boostThreshold,crisp,depth,edgeColor,edgeWidth,groupZPadding
|
|
* @product highcharts
|
|
* @sample {highcharts} highcharts/demo/variwide/
|
|
* Variwide chart
|
|
* @since 6.0.0
|
|
* @optionparent plotOptions.variwide
|
|
*/
|
|
seriesType('variwide', 'column', {
|
|
/**
|
|
* In a variwide chart, the point padding is 0 in order to express the
|
|
* horizontal stacking of items.
|
|
*/
|
|
pointPadding: 0,
|
|
/**
|
|
* In a variwide chart, the group padding is 0 in order to express the
|
|
* horizontal stacking of items.
|
|
*/
|
|
groupPadding: 0
|
|
}, {
|
|
pointArrayMap: ['y', 'z'],
|
|
parallelArrays: ['x', 'y', 'z'],
|
|
processData: function() {
|
|
var series = this;
|
|
this.totalZ = 0;
|
|
this.relZ = [];
|
|
seriesTypes.column.prototype.processData.call(this);
|
|
|
|
each(this.zData, function(z, i) {
|
|
series.relZ[i] = series.totalZ;
|
|
series.totalZ += z;
|
|
});
|
|
|
|
if (this.xAxis.categories) {
|
|
this.xAxis.variwide = true;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Translate an x value inside a given category index into the distorted
|
|
* axis translation.
|
|
* @param {Number} index The category index
|
|
* @param {Number} x The X pixel position in undistorted axis pixels
|
|
* @return {Number} Distorted X position
|
|
*/
|
|
postTranslate: function(index, x) {
|
|
|
|
var axis = this.xAxis,
|
|
relZ = this.relZ,
|
|
i = index,
|
|
len = axis.len,
|
|
totalZ = this.totalZ,
|
|
linearSlotLeft = i / relZ.length * len,
|
|
linearSlotRight = (i + 1) / relZ.length * len,
|
|
slotLeft = (pick(relZ[i], totalZ) / totalZ) * len,
|
|
slotRight = (pick(relZ[i + 1], totalZ) / totalZ) * len,
|
|
xInsideLinearSlot = x - linearSlotLeft,
|
|
ret;
|
|
|
|
ret = slotLeft +
|
|
xInsideLinearSlot * (slotRight - slotLeft) /
|
|
(linearSlotRight - linearSlotLeft);
|
|
|
|
return ret;
|
|
},
|
|
|
|
/**
|
|
* Extend translation by distoring X position based on Z.
|
|
*/
|
|
translate: function() {
|
|
|
|
// Temporarily disable crisping when computing original shapeArgs
|
|
var crispOption = this.options.crisp;
|
|
this.options.crisp = false;
|
|
|
|
seriesTypes.column.prototype.translate.call(this);
|
|
|
|
// Reset option
|
|
this.options.crisp = crispOption;
|
|
|
|
var inverted = this.chart.inverted,
|
|
crisp = this.borderWidth % 2 / 2;
|
|
|
|
// Distort the points to reflect z dimension
|
|
each(this.points, function(point, i) {
|
|
var left = this.postTranslate(
|
|
i,
|
|
point.shapeArgs.x
|
|
),
|
|
right = this.postTranslate(
|
|
i,
|
|
point.shapeArgs.x + point.shapeArgs.width
|
|
);
|
|
|
|
if (this.options.crisp) {
|
|
left = Math.round(left) - crisp;
|
|
right = Math.round(right) - crisp;
|
|
}
|
|
|
|
point.shapeArgs.x = left;
|
|
point.shapeArgs.width = right - left;
|
|
|
|
point.tooltipPos[inverted ? 1 : 0] = this.postTranslate(
|
|
i,
|
|
point.tooltipPos[inverted ? 1 : 0]
|
|
);
|
|
}, this);
|
|
}
|
|
|
|
// Point functions
|
|
}, {
|
|
isValid: function() {
|
|
return H.isNumber(this.y, true) && H.isNumber(this.z, true);
|
|
}
|
|
});
|
|
|
|
H.Tick.prototype.postTranslate = function(xy, xOrY, index) {
|
|
xy[xOrY] = this.axis.pos +
|
|
this.axis.series[0].postTranslate(index, xy[xOrY] - this.axis.pos);
|
|
};
|
|
|
|
H.wrap(H.Tick.prototype, 'getPosition', function(proceed, horiz, pos) {
|
|
var axis = this.axis,
|
|
xy = proceed.apply(this, Array.prototype.slice.call(arguments, 1)),
|
|
xOrY = horiz ? 'x' : 'y';
|
|
|
|
if (axis.categories && axis.variwide) {
|
|
this[xOrY + 'Orig'] = xy[xOrY];
|
|
this.postTranslate(xy, xOrY, pos);
|
|
}
|
|
return xy;
|
|
});
|
|
|
|
H.wrap(H.Tick.prototype, 'getLabelPosition', function(
|
|
proceed,
|
|
x,
|
|
y,
|
|
label,
|
|
horiz,
|
|
labelOptions,
|
|
tickmarkOffset,
|
|
index
|
|
) {
|
|
var args = Array.prototype.slice.call(arguments, 1),
|
|
xy,
|
|
xOrY = horiz ? 'x' : 'y';
|
|
|
|
// Replace the x with the original x
|
|
if (this.axis.variwide && typeof this[xOrY + 'Orig'] === 'number') {
|
|
args[horiz ? 0 : 1] = this[xOrY + 'Orig'];
|
|
}
|
|
|
|
xy = proceed.apply(this, args);
|
|
|
|
// Post-translate
|
|
if (this.axis.variwide && this.axis.categories) {
|
|
this.postTranslate(xy, xOrY, index);
|
|
}
|
|
return xy;
|
|
});
|
|
|
|
|
|
|
|
/**
|
|
* A `variwide` series. If the [type](#series.variwide.type) option is
|
|
* not specified, it is inherited from [chart.type](#chart.type).
|
|
*
|
|
* For options that apply to multiple series, it is recommended to add
|
|
* them to the [plotOptions.series](#plotOptions.series) options structure.
|
|
* To apply to all series of this specific type, apply it to [plotOptions.
|
|
* variwide](#plotOptions.variwide).
|
|
*
|
|
* @type {Object}
|
|
* @extends series,plotOptions.variwide
|
|
* @product highcharts
|
|
* @apioption series.variwide
|
|
*/
|
|
|
|
/**
|
|
* An array of data points for the series. For the `variwide` series type,
|
|
* points can be given in the following ways:
|
|
*
|
|
* 1. An array of arrays with 3 or 2 values. In this case, the values
|
|
* correspond to `x,y,z`. If the first value is a string, it is applied
|
|
* as the name of the point, and the `x` value is inferred. The `x`
|
|
* value can also be omitted, in which case the inner arrays should
|
|
* be of length 2\. Then the `x` value is automatically calculated,
|
|
* either starting at 0 and incremented by 1, or from `pointStart` and
|
|
* `pointInterval` given in the series options.
|
|
*
|
|
* ```js
|
|
* data: [
|
|
* [0, 1, 2],
|
|
* [1, 5, 5],
|
|
* [2, 0, 2]
|
|
* ]
|
|
* ```
|
|
*
|
|
* 2. An array of objects with named values. The objects are point
|
|
* configuration objects as seen below. If the total number of data
|
|
* points exceeds the series' [turboThreshold](#series.variwide.turboThreshold),
|
|
* this option is not available.
|
|
*
|
|
* ```js
|
|
* data: [{
|
|
* x: 1,
|
|
* y: 1,
|
|
* z: 1,
|
|
* name: "Point2",
|
|
* color: "#00FF00"
|
|
* }, {
|
|
* x: 1,
|
|
* y: 5,
|
|
* z: 4,
|
|
* name: "Point1",
|
|
* color: "#FF00FF"
|
|
* }]
|
|
* ```
|
|
*
|
|
* @type {Array<Object|Array>}
|
|
* @extends series.line.data
|
|
* @excluding marker
|
|
* @sample {highcharts} highcharts/chart/reflow-true/ Numerical values
|
|
* @sample {highcharts} highcharts/series/data-array-of-arrays/ Arrays of numeric x and y
|
|
* @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ Arrays of datetime x and y
|
|
* @sample {highcharts} highcharts/series/data-array-of-name-value/ Arrays of point.name and y
|
|
* @sample {highcharts} highcharts/series/data-array-of-objects/ Config objects
|
|
* @product highcharts
|
|
* @apioption series.variwide.data
|
|
*/
|
|
|
|
/**
|
|
* The relative width for each column. The widths are distributed so they sum
|
|
* up to the X axis length.
|
|
*
|
|
* @type {Number}
|
|
* @product highcharts
|
|
* @apioption series.variwide.data.z
|
|
*/
|
|
|
|
}(Highcharts));
|
|
}));
|