variwide.src.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /**
  2. * @license Highcharts JS v8.2.0 (2020-08-20)
  3. *
  4. * Highcharts variwide module
  5. *
  6. * (c) 2010-2019 Torstein Honsi
  7. *
  8. * License: www.highcharts.com/license
  9. */
  10. 'use strict';
  11. (function (factory) {
  12. if (typeof module === 'object' && module.exports) {
  13. factory['default'] = factory;
  14. module.exports = factory;
  15. } else if (typeof define === 'function' && define.amd) {
  16. define('highcharts/modules/variwide', ['highcharts'], function (Highcharts) {
  17. factory(Highcharts);
  18. factory.Highcharts = Highcharts;
  19. return factory;
  20. });
  21. } else {
  22. factory(typeof Highcharts !== 'undefined' ? Highcharts : undefined);
  23. }
  24. }(function (Highcharts) {
  25. var _modules = Highcharts ? Highcharts._modules : {};
  26. function _registerModule(obj, path, args, fn) {
  27. if (!obj.hasOwnProperty(path)) {
  28. obj[path] = fn.apply(null, args);
  29. }
  30. }
  31. _registerModule(_modules, 'Series/VariwideSeries.js', [_modules['Core/Globals.js'], _modules['Core/Utilities.js']], function (H, U) {
  32. /* *
  33. *
  34. * Highcharts variwide module
  35. *
  36. * (c) 2010-2020 Torstein Honsi
  37. *
  38. * License: www.highcharts.com/license
  39. *
  40. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  41. *
  42. * */
  43. var addEvent = U.addEvent,
  44. isNumber = U.isNumber,
  45. pick = U.pick,
  46. seriesType = U.seriesType,
  47. wrap = U.wrap;
  48. var seriesTypes = H.seriesTypes;
  49. /**
  50. * @private
  51. * @class
  52. * @name Highcharts.seriesTypes.variwide
  53. *
  54. * @augments Highcharts.Series
  55. */
  56. seriesType('variwide', 'column'
  57. /**
  58. * A variwide chart (related to marimekko chart) is a column chart with a
  59. * variable width expressing a third dimension.
  60. *
  61. * @sample {highcharts} highcharts/demo/variwide/
  62. * Variwide chart
  63. * @sample {highcharts} highcharts/series-variwide/inverted/
  64. * Inverted variwide chart
  65. * @sample {highcharts} highcharts/series-variwide/datetime/
  66. * Variwide columns on a datetime axis
  67. *
  68. * @extends plotOptions.column
  69. * @since 6.0.0
  70. * @product highcharts
  71. * @excluding boostThreshold, crisp, depth, edgeColor, edgeWidth,
  72. * groupZPadding, boostBlending
  73. * @requires modules/variwide
  74. * @optionparent plotOptions.variwide
  75. */
  76. , {
  77. /**
  78. * In a variwide chart, the point padding is 0 in order to express the
  79. * horizontal stacking of items.
  80. */
  81. pointPadding: 0,
  82. /**
  83. * In a variwide chart, the group padding is 0 in order to express the
  84. * horizontal stacking of items.
  85. */
  86. groupPadding: 0
  87. }, {
  88. irregularWidths: true,
  89. pointArrayMap: ['y', 'z'],
  90. parallelArrays: ['x', 'y', 'z'],
  91. processData: function (force) {
  92. this.totalZ = 0;
  93. this.relZ = [];
  94. seriesTypes.column.prototype.processData.call(this, force);
  95. (this.xAxis.reversed ?
  96. this.zData.slice().reverse() :
  97. this.zData).forEach(function (z, i) {
  98. this.relZ[i] = this.totalZ;
  99. this.totalZ += z;
  100. }, this);
  101. if (this.xAxis.categories) {
  102. this.xAxis.variwide = true;
  103. this.xAxis.zData = this.zData; // Used for label rank
  104. }
  105. return;
  106. },
  107. /* eslint-disable valid-jsdoc */
  108. /**
  109. * Translate an x value inside a given category index into the distorted
  110. * axis translation.
  111. *
  112. * @private
  113. * @function Highcharts.Series#postTranslate
  114. *
  115. * @param {number} index
  116. * The category index
  117. *
  118. * @param {number} x
  119. * The X pixel position in undistorted axis pixels
  120. *
  121. * @param {Highcharts.Point} point
  122. * For crosshairWidth for every point
  123. *
  124. * @return {number}
  125. * Distorted X position
  126. */
  127. postTranslate: function (index, x, point) {
  128. var axis = this.xAxis,
  129. relZ = this.relZ,
  130. i = axis.reversed ? relZ.length - index : index,
  131. goRight = axis.reversed ? -1 : 1,
  132. len = axis.len,
  133. totalZ = this.totalZ,
  134. linearSlotLeft = i / relZ.length * len,
  135. linearSlotRight = (i + goRight) / relZ.length * len,
  136. slotLeft = (pick(relZ[i],
  137. totalZ) / totalZ) * len,
  138. slotRight = (pick(relZ[i + goRight],
  139. totalZ) / totalZ) * len,
  140. xInsideLinearSlot = x - linearSlotLeft,
  141. ret;
  142. // Set crosshairWidth for every point (#8173)
  143. if (point) {
  144. point.crosshairWidth = slotRight - slotLeft;
  145. }
  146. ret = slotLeft +
  147. xInsideLinearSlot * (slotRight - slotLeft) /
  148. (linearSlotRight - linearSlotLeft);
  149. return ret;
  150. },
  151. /* eslint-enable valid-jsdoc */
  152. // Extend translation by distoring X position based on Z.
  153. translate: function () {
  154. // Temporarily disable crisping when computing original shapeArgs
  155. var crispOption = this.options.crisp,
  156. xAxis = this.xAxis;
  157. this.options.crisp = false;
  158. seriesTypes.column.prototype.translate.call(this);
  159. // Reset option
  160. this.options.crisp = crispOption;
  161. var inverted = this.chart.inverted,
  162. crisp = this.borderWidth % 2 / 2;
  163. // Distort the points to reflect z dimension
  164. this.points.forEach(function (point, i) {
  165. var left,
  166. right;
  167. if (xAxis.variwide) {
  168. left = this.postTranslate(i, point.shapeArgs.x, point);
  169. right = this.postTranslate(i, point.shapeArgs.x +
  170. point.shapeArgs.width);
  171. // For linear or datetime axes, the variwide column should
  172. // start with X and extend Z units, without modifying the
  173. // axis.
  174. }
  175. else {
  176. left = point.plotX;
  177. right = xAxis.translate(point.x + point.z, 0, 0, 0, 1);
  178. }
  179. if (this.options.crisp) {
  180. left = Math.round(left) - crisp;
  181. right = Math.round(right) - crisp;
  182. }
  183. point.shapeArgs.x = left;
  184. point.shapeArgs.width = Math.max(right - left, 1);
  185. // Crosshair position (#8083)
  186. point.plotX = (left + right) / 2;
  187. // Adjust the tooltip position
  188. if (!inverted) {
  189. point.tooltipPos[0] =
  190. point.shapeArgs.x +
  191. point.shapeArgs.width / 2;
  192. }
  193. else {
  194. point.tooltipPos[1] =
  195. xAxis.len - point.shapeArgs.x -
  196. point.shapeArgs.width / 2;
  197. }
  198. }, this);
  199. if (this.options.stacking) {
  200. this.correctStackLabels();
  201. }
  202. },
  203. // Function that corrects stack labels positions
  204. correctStackLabels: function () {
  205. var series = this,
  206. options = series.options,
  207. yAxis = series.yAxis,
  208. pointStack,
  209. pointWidth,
  210. stack,
  211. xValue;
  212. series.points.forEach(function (point) {
  213. xValue = point.x;
  214. pointWidth = point.shapeArgs.width;
  215. stack = yAxis.stacking.stacks[(series.negStacks &&
  216. point.y < (options.startFromThreshold ?
  217. 0 :
  218. options.threshold) ?
  219. '-' :
  220. '') + series.stackKey];
  221. if (stack) {
  222. pointStack = stack[xValue];
  223. if (pointStack && !point.isNull) {
  224. pointStack.setOffset(-(pointWidth / 2) || 0, pointWidth || 0, void 0, void 0, point.plotX);
  225. }
  226. }
  227. });
  228. }
  229. // Point functions
  230. }, {
  231. isValid: function () {
  232. return isNumber(this.y) && isNumber(this.z);
  233. }
  234. });
  235. H.Tick.prototype.postTranslate = function (xy, xOrY, index) {
  236. var axis = this.axis,
  237. pos = xy[xOrY] - axis.pos;
  238. if (!axis.horiz) {
  239. pos = axis.len - pos;
  240. }
  241. pos = axis.series[0].postTranslate(index, pos);
  242. if (!axis.horiz) {
  243. pos = axis.len - pos;
  244. }
  245. xy[xOrY] = axis.pos + pos;
  246. };
  247. /* eslint-disable no-invalid-this */
  248. // Same width as the category (#8083)
  249. addEvent(H.Axis, 'afterDrawCrosshair', function (e) {
  250. if (this.variwide && this.cross) {
  251. this.cross.attr('stroke-width', (e.point && e.point.crosshairWidth));
  252. }
  253. });
  254. // On a vertical axis, apply anti-collision logic to the labels.
  255. addEvent(H.Axis, 'afterRender', function () {
  256. var axis = this;
  257. if (!this.horiz && this.variwide) {
  258. this.chart.labelCollectors.push(function () {
  259. return axis.tickPositions
  260. .filter(function (pos) {
  261. return axis.ticks[pos].label;
  262. })
  263. .map(function (pos, i) {
  264. var label = axis.ticks[pos].label;
  265. label.labelrank = axis.zData[i];
  266. return label;
  267. });
  268. });
  269. }
  270. });
  271. addEvent(H.Tick, 'afterGetPosition', function (e) {
  272. var axis = this.axis,
  273. xOrY = axis.horiz ? 'x' : 'y';
  274. if (axis.variwide) {
  275. this[xOrY + 'Orig'] = e.pos[xOrY];
  276. this.postTranslate(e.pos, xOrY, this.pos);
  277. }
  278. });
  279. wrap(H.Tick.prototype, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index) {
  280. var args = Array.prototype.slice.call(arguments, 1),
  281. xy,
  282. xOrY = horiz ? 'x' : 'y';
  283. // Replace the x with the original x
  284. if (this.axis.variwide &&
  285. typeof this[xOrY + 'Orig'] === 'number') {
  286. args[horiz ? 0 : 1] = this[xOrY + 'Orig'];
  287. }
  288. xy = proceed.apply(this, args);
  289. // Post-translate
  290. if (this.axis.variwide && this.axis.categories) {
  291. this.postTranslate(xy, xOrY, index);
  292. }
  293. return xy;
  294. });
  295. /**
  296. * A `variwide` series. If the [type](#series.variwide.type) option is not
  297. * specified, it is inherited from [chart.type](#chart.type).
  298. *
  299. * @extends series,plotOptions.variwide
  300. * @excluding boostThreshold, boostBlending
  301. * @product highcharts
  302. * @requires modules/variwide
  303. * @apioption series.variwide
  304. */
  305. /**
  306. * An array of data points for the series. For the `variwide` series type,
  307. * points can be given in the following ways:
  308. *
  309. * 1. An array of arrays with 3 or 2 values. In this case, the values correspond
  310. * to `x,y,z`. If the first value is a string, it is applied as the name of
  311. * the point, and the `x` value is inferred. The `x` value can also be
  312. * omitted, in which case the inner arrays should be of length 2. Then the
  313. * `x` value is automatically calculated, either starting at 0 and
  314. * incremented by 1, or from `pointStart` and `pointInterval` given in the
  315. * series options.
  316. * ```js
  317. * data: [
  318. * [0, 1, 2],
  319. * [1, 5, 5],
  320. * [2, 0, 2]
  321. * ]
  322. * ```
  323. *
  324. * 2. An array of objects with named values. The following snippet shows only a
  325. * few settings, see the complete options set below. If the total number of
  326. * data points exceeds the series'
  327. * [turboThreshold](#series.variwide.turboThreshold), this option is not
  328. * available.
  329. * ```js
  330. * data: [{
  331. * x: 1,
  332. * y: 1,
  333. * z: 1,
  334. * name: "Point2",
  335. * color: "#00FF00"
  336. * }, {
  337. * x: 1,
  338. * y: 5,
  339. * z: 4,
  340. * name: "Point1",
  341. * color: "#FF00FF"
  342. * }]
  343. * ```
  344. *
  345. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  346. * Arrays of numeric x and y
  347. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  348. * Arrays of datetime x and y
  349. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  350. * Arrays of point.name and y
  351. * @sample {highcharts} highcharts/series/data-array-of-objects/
  352. * Config objects
  353. *
  354. * @type {Array<Array<(number|string),number>|Array<(number|string),number,number>|*>}
  355. * @extends series.line.data
  356. * @excluding marker
  357. * @product highcharts
  358. * @apioption series.variwide.data
  359. */
  360. /**
  361. * The relative width for each column. On a category axis, the widths are
  362. * distributed so they sum up to the X axis length. On linear and datetime axes,
  363. * the columns will be laid out from the X value and Z units along the axis.
  364. *
  365. * @type {number}
  366. * @product highcharts
  367. * @apioption series.variwide.data.z
  368. */
  369. ''; // adds doclets above to transpiled file
  370. });
  371. _registerModule(_modules, 'masters/modules/variwide.src.js', [], function () {
  372. });
  373. }));