ColumnSeries.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. /* *
  2. *
  3. * (c) 2010-2021 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. var __extends = (this && this.__extends) || (function () {
  12. var extendStatics = function (d, b) {
  13. extendStatics = Object.setPrototypeOf ||
  14. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  15. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  16. return extendStatics(d, b);
  17. };
  18. return function (d, b) {
  19. extendStatics(d, b);
  20. function __() { this.constructor = d; }
  21. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  22. };
  23. })();
  24. import A from '../../Core/Animation/AnimationUtilities.js';
  25. var animObject = A.animObject;
  26. import Color from '../../Core/Color/Color.js';
  27. var color = Color.parse;
  28. import H from '../../Core/Globals.js';
  29. var hasTouch = H.hasTouch, noop = H.noop;
  30. import LegendSymbolMixin from '../../Mixins/LegendSymbol.js';
  31. import palette from '../../Core/Color/Palette.js';
  32. import Series from '../../Core/Series/Series.js';
  33. import SeriesRegistry from '../../Core/Series/SeriesRegistry.js';
  34. import U from '../../Core/Utilities.js';
  35. var clamp = U.clamp, css = U.css, defined = U.defined, extend = U.extend, fireEvent = U.fireEvent, isArray = U.isArray, isNumber = U.isNumber, merge = U.merge, pick = U.pick, objectEach = U.objectEach;
  36. /**
  37. * The column series type.
  38. *
  39. * @private
  40. * @class
  41. * @name Highcharts.seriesTypes.column
  42. *
  43. * @augments Highcharts.Series
  44. */
  45. var ColumnSeries = /** @class */ (function (_super) {
  46. __extends(ColumnSeries, _super);
  47. function ColumnSeries() {
  48. /* *
  49. *
  50. * Static Properties
  51. *
  52. * */
  53. var _this = _super !== null && _super.apply(this, arguments) || this;
  54. /* *
  55. *
  56. * Properties
  57. *
  58. * */
  59. _this.borderWidth = void 0;
  60. _this.data = void 0;
  61. _this.group = void 0;
  62. _this.options = void 0;
  63. _this.points = void 0;
  64. return _this;
  65. /* eslint-enable valid-jsdoc */
  66. }
  67. /* *
  68. *
  69. * Functions
  70. *
  71. * */
  72. /* eslint-disable valid-jsdoc */
  73. /**
  74. * Animate the column heights one by one from zero.
  75. *
  76. * @private
  77. * @function Highcharts.seriesTypes.column#animate
  78. *
  79. * @param {boolean} init
  80. * Whether to initialize the animation or run it
  81. */
  82. ColumnSeries.prototype.animate = function (init) {
  83. var series = this, yAxis = this.yAxis, options = series.options, inverted = this.chart.inverted, attr = {}, translateProp = inverted ? 'translateX' : 'translateY', translateStart, translatedThreshold;
  84. if (init) {
  85. attr.scaleY = 0.001;
  86. translatedThreshold = clamp(yAxis.toPixels(options.threshold), yAxis.pos, yAxis.pos + yAxis.len);
  87. if (inverted) {
  88. attr.translateX = translatedThreshold - yAxis.len;
  89. }
  90. else {
  91. attr.translateY = translatedThreshold;
  92. }
  93. // apply finnal clipping (used in Highstock) (#7083)
  94. // animation is done by scaleY, so cliping is for panes
  95. if (series.clipBox) {
  96. series.setClip();
  97. }
  98. series.group.attr(attr);
  99. }
  100. else { // run the animation
  101. translateStart = series.group.attr(translateProp);
  102. series.group.animate({ scaleY: 1 }, extend(animObject(series.options.animation), {
  103. // Do the scale synchronously to ensure smooth
  104. // updating (#5030, #7228)
  105. step: function (val, fx) {
  106. if (series.group) {
  107. attr[translateProp] = translateStart +
  108. fx.pos * (yAxis.pos - translateStart);
  109. series.group.attr(attr);
  110. }
  111. }
  112. }));
  113. }
  114. };
  115. /**
  116. * Initialize the series. Extends the basic Series.init method by
  117. * marking other series of the same type as dirty.
  118. *
  119. * @private
  120. * @function Highcharts.seriesTypes.column#init
  121. */
  122. ColumnSeries.prototype.init = function (chart, options) {
  123. _super.prototype.init.apply(this, arguments);
  124. var series = this, chart = series.chart;
  125. // if the series is added dynamically, force redraw of other
  126. // series affected by a new column
  127. if (chart.hasRendered) {
  128. chart.series.forEach(function (otherSeries) {
  129. if (otherSeries.type === series.type) {
  130. otherSeries.isDirty = true;
  131. }
  132. });
  133. }
  134. };
  135. /**
  136. * Return the width and x offset of the columns adjusted for grouping,
  137. * groupPadding, pointPadding, pointWidth etc.
  138. *
  139. * @private
  140. * @function Highcharts.seriesTypes.column#getColumnMetrics
  141. * @return {Highcharts.ColumnMetricsObject}
  142. */
  143. ColumnSeries.prototype.getColumnMetrics = function () {
  144. var series = this, options = series.options, xAxis = series.xAxis, yAxis = series.yAxis, reversedStacks = xAxis.options.reversedStacks,
  145. // Keep backward compatibility: reversed xAxis had reversed
  146. // stacks
  147. reverseStacks = (xAxis.reversed && !reversedStacks) ||
  148. (!xAxis.reversed && reversedStacks), stackKey, stackGroups = {}, columnCount = 0;
  149. // Get the total number of column type series. This is called on
  150. // every series. Consider moving this logic to a chart.orderStacks()
  151. // function and call it on init, addSeries and removeSeries
  152. if (options.grouping === false) {
  153. columnCount = 1;
  154. }
  155. else {
  156. series.chart.series.forEach(function (otherSeries) {
  157. var otherYAxis = otherSeries.yAxis, otherOptions = otherSeries.options, columnIndex;
  158. if (otherSeries.type === series.type &&
  159. (otherSeries.visible ||
  160. !series.chart.options.chart
  161. .ignoreHiddenSeries) &&
  162. yAxis.len === otherYAxis.len &&
  163. yAxis.pos === otherYAxis.pos) { // #642, #2086
  164. if (otherOptions.stacking && otherOptions.stacking !== 'group') {
  165. stackKey = otherSeries.stackKey;
  166. if (typeof stackGroups[stackKey] ===
  167. 'undefined') {
  168. stackGroups[stackKey] = columnCount++;
  169. }
  170. columnIndex = stackGroups[stackKey];
  171. }
  172. else if (otherOptions.grouping !== false) { // #1162
  173. columnIndex = columnCount++;
  174. }
  175. otherSeries.columnIndex = columnIndex;
  176. }
  177. });
  178. }
  179. var categoryWidth = Math.min(Math.abs(xAxis.transA) * ((xAxis.ordinal && xAxis.ordinal.slope) ||
  180. options.pointRange ||
  181. xAxis.closestPointRange ||
  182. xAxis.tickInterval ||
  183. 1), // #2610
  184. xAxis.len // #1535
  185. ), groupPadding = categoryWidth * options.groupPadding, groupWidth = categoryWidth - 2 * groupPadding, pointOffsetWidth = groupWidth / (columnCount || 1), pointWidth = Math.min(options.maxPointWidth || xAxis.len, pick(options.pointWidth, pointOffsetWidth * (1 - 2 * options.pointPadding))), pointPadding = (pointOffsetWidth - pointWidth) / 2,
  186. // #1251, #3737
  187. colIndex = (series.columnIndex || 0) + (reverseStacks ? 1 : 0), pointXOffset = pointPadding +
  188. (groupPadding +
  189. colIndex * pointOffsetWidth -
  190. (categoryWidth / 2)) * (reverseStacks ? -1 : 1);
  191. // Save it for reading in linked series (Error bars particularly)
  192. series.columnMetrics = {
  193. width: pointWidth,
  194. offset: pointXOffset,
  195. paddedWidth: pointOffsetWidth,
  196. columnCount: columnCount
  197. };
  198. return series.columnMetrics;
  199. };
  200. /**
  201. * Make the columns crisp. The edges are rounded to the nearest full
  202. * pixel.
  203. *
  204. * @private
  205. * @function Highcharts.seriesTypes.column#crispCol
  206. */
  207. ColumnSeries.prototype.crispCol = function (x, y, w, h) {
  208. var chart = this.chart, borderWidth = this.borderWidth, xCrisp = -(borderWidth % 2 ? 0.5 : 0), yCrisp = borderWidth % 2 ? 0.5 : 1, right, bottom, fromTop;
  209. if (chart.inverted && chart.renderer.isVML) {
  210. yCrisp += 1;
  211. }
  212. // Horizontal. We need to first compute the exact right edge, then
  213. // round it and compute the width from there.
  214. if (this.options.crisp) {
  215. right = Math.round(x + w) + xCrisp;
  216. x = Math.round(x) + xCrisp;
  217. w = right - x;
  218. }
  219. // Vertical
  220. bottom = Math.round(y + h) + yCrisp;
  221. fromTop = Math.abs(y) <= 0.5 && bottom > 0.5; // #4504, #4656
  222. y = Math.round(y) + yCrisp;
  223. h = bottom - y;
  224. // Top edges are exceptions
  225. if (fromTop && h) { // #5146
  226. y -= 1;
  227. h += 1;
  228. }
  229. return {
  230. x: x,
  231. y: y,
  232. width: w,
  233. height: h
  234. };
  235. };
  236. /**
  237. * Adjust for missing columns, according to the `centerInCategory`
  238. * option. Missing columns are either single points or stacks where the
  239. * point or points are either missing or null.
  240. *
  241. * @private
  242. * @function Highcharts.seriesTypes.column#adjustForMissingColumns
  243. * @param {number} x
  244. * The x coordinate of the column, left side
  245. *
  246. * @param {number} pointWidth
  247. * The pointWidth, already computed upstream
  248. *
  249. * @param {Highcharts.ColumnPoint} point
  250. * The point instance
  251. *
  252. * @param {Highcharts.ColumnMetricsObject} metrics
  253. * The series-wide column metrics
  254. *
  255. * @return {number}
  256. * The adjusted x position, or the original if not adjusted
  257. */
  258. ColumnSeries.prototype.adjustForMissingColumns = function (x, pointWidth, point, metrics) {
  259. var _this = this;
  260. var stacking = this.options.stacking;
  261. if (!point.isNull && metrics.columnCount > 1) {
  262. var indexInCategory_1 = 0;
  263. var totalInCategory_1 = 0;
  264. // Loop over all the stacks on the Y axis. When stacking is
  265. // enabled, these are real point stacks. When stacking is not
  266. // enabled, but `centerInCategory` is true, there is one stack
  267. // handling the grouping of points in each category. This is
  268. // done in the `setGroupedPoints` function.
  269. objectEach(this.yAxis.stacking && this.yAxis.stacking.stacks, function (stack) {
  270. if (typeof point.x === 'number') {
  271. var stackItem = stack[point.x.toString()];
  272. if (stackItem) {
  273. var pointValues = stackItem.points[_this.index], total = stackItem.total;
  274. // If true `stacking` is enabled, count the
  275. // total number of non-null stacks in the
  276. // category, and note which index this point is
  277. // within those stacks.
  278. if (stacking) {
  279. if (pointValues) {
  280. indexInCategory_1 = totalInCategory_1;
  281. }
  282. if (stackItem.hasValidPoints) {
  283. totalInCategory_1++;
  284. }
  285. // If `stacking` is not enabled, look for the
  286. // index and total of the `group` stack.
  287. }
  288. else if (isArray(pointValues)) {
  289. indexInCategory_1 = pointValues[1];
  290. totalInCategory_1 = total || 0;
  291. }
  292. }
  293. }
  294. });
  295. // Compute the adjusted x position
  296. var boxWidth = (totalInCategory_1 - 1) * metrics.paddedWidth +
  297. pointWidth;
  298. x = (point.plotX || 0) + boxWidth / 2 - pointWidth -
  299. indexInCategory_1 * metrics.paddedWidth;
  300. }
  301. return x;
  302. };
  303. /**
  304. * Translate each point to the plot area coordinate system and find
  305. * shape positions
  306. *
  307. * @private
  308. * @function Highcharts.seriesTypes.column#translate
  309. */
  310. ColumnSeries.prototype.translate = function () {
  311. var series = this, chart = series.chart, options = series.options, dense = series.dense =
  312. series.closestPointRange * series.xAxis.transA < 2, borderWidth = series.borderWidth = pick(options.borderWidth, dense ? 0 : 1 // #3635
  313. ), xAxis = series.xAxis, yAxis = series.yAxis, threshold = options.threshold, translatedThreshold = series.translatedThreshold =
  314. yAxis.getThreshold(threshold), minPointLength = pick(options.minPointLength, 5), metrics = series.getColumnMetrics(), seriesPointWidth = metrics.width,
  315. // postprocessed for border width
  316. seriesBarW = series.barW =
  317. Math.max(seriesPointWidth, 1 + 2 * borderWidth), seriesXOffset = series.pointXOffset = metrics.offset, dataMin = series.dataMin, dataMax = series.dataMax;
  318. if (chart.inverted) {
  319. translatedThreshold -= 0.5; // #3355
  320. }
  321. // When the pointPadding is 0, we want the columns to be packed
  322. // tightly, so we allow individual columns to have individual sizes.
  323. // When pointPadding is greater, we strive for equal-width columns
  324. // (#2694).
  325. if (options.pointPadding) {
  326. seriesBarW = Math.ceil(seriesBarW);
  327. }
  328. Series.prototype.translate.apply(series);
  329. // Record the new values
  330. series.points.forEach(function (point) {
  331. var yBottom = pick(point.yBottom, translatedThreshold), safeDistance = 999 + Math.abs(yBottom), pointWidth = seriesPointWidth, plotX = point.plotX || 0,
  332. // Don't draw too far outside plot area (#1303, #2241,
  333. // #4264)
  334. plotY = clamp(point.plotY, -safeDistance, yAxis.len + safeDistance), barX = plotX + seriesXOffset, barW = seriesBarW, barY = Math.min(plotY, yBottom), up, barH = Math.max(plotY, yBottom) - barY;
  335. // Handle options.minPointLength
  336. if (minPointLength && Math.abs(barH) < minPointLength) {
  337. barH = minPointLength;
  338. up = (!yAxis.reversed && !point.negative) ||
  339. (yAxis.reversed && point.negative);
  340. // Reverse zeros if there's no positive value in the series
  341. // in visible range (#7046)
  342. if (isNumber(threshold) &&
  343. isNumber(dataMax) &&
  344. point.y === threshold &&
  345. dataMax <= threshold &&
  346. // and if there's room for it (#7311)
  347. (yAxis.min || 0) < threshold &&
  348. // if all points are the same value (i.e zero) not draw
  349. // as negative points (#10646), but only if there's room
  350. // for it (#14876)
  351. (dataMin !== dataMax || (yAxis.max || 0) <= threshold)) {
  352. up = !up;
  353. }
  354. // If stacked...
  355. barY = (Math.abs(barY - translatedThreshold) > minPointLength ?
  356. // ...keep position
  357. yBottom - minPointLength :
  358. // #1485, #4051
  359. translatedThreshold -
  360. (up ? minPointLength : 0));
  361. }
  362. // Handle point.options.pointWidth
  363. // @todo Handle grouping/stacking too. Calculate offset properly
  364. if (defined(point.options.pointWidth)) {
  365. pointWidth = barW =
  366. Math.ceil(point.options.pointWidth);
  367. barX -= Math.round((pointWidth - seriesPointWidth) / 2);
  368. }
  369. // Adjust for null or missing points
  370. if (options.centerInCategory) {
  371. barX = series.adjustForMissingColumns(barX, pointWidth, point, metrics);
  372. }
  373. // Cache for access in polar
  374. point.barX = barX;
  375. point.pointWidth = pointWidth;
  376. // Fix the tooltip on center of grouped columns (#1216, #424,
  377. // #3648)
  378. point.tooltipPos = chart.inverted ?
  379. [
  380. clamp(yAxis.len + yAxis.pos - chart.plotLeft - plotY, yAxis.pos - chart.plotLeft, yAxis.len + yAxis.pos - chart.plotLeft),
  381. xAxis.len + xAxis.pos - chart.plotTop - (plotX || 0) - seriesXOffset - barW / 2,
  382. barH
  383. ] :
  384. [
  385. xAxis.left - chart.plotLeft + barX + barW / 2,
  386. clamp(plotY + yAxis.pos -
  387. chart.plotTop, yAxis.pos - chart.plotTop, yAxis.len + yAxis.pos - chart.plotTop),
  388. barH
  389. ];
  390. // Register shape type and arguments to be used in drawPoints
  391. // Allow shapeType defined on pointClass level
  392. point.shapeType = series.pointClass.prototype.shapeType || 'rect';
  393. point.shapeArgs = series.crispCol.apply(series, point.isNull ?
  394. // #3169, drilldown from null must have a position to work
  395. // from #6585, dataLabel should be placed on xAxis, not
  396. // floating in the middle of the chart
  397. [barX, translatedThreshold, barW, 0] :
  398. [barX, barY, barW, barH]);
  399. });
  400. };
  401. /**
  402. * Columns have no graph
  403. *
  404. * @private
  405. * @function Highcharts.seriesTypes.column#drawGraph
  406. */
  407. ColumnSeries.prototype.drawGraph = function () {
  408. this.group[this.dense ? 'addClass' : 'removeClass']('highcharts-dense-data');
  409. };
  410. /**
  411. * Get presentational attributes
  412. *
  413. * @private
  414. * @function Highcharts.seriesTypes.column#pointAttribs
  415. */
  416. ColumnSeries.prototype.pointAttribs = function (point, state) {
  417. var options = this.options, stateOptions, ret, p2o = this.pointAttrToOptions || {}, strokeOption = p2o.stroke || 'borderColor', strokeWidthOption = p2o['stroke-width'] || 'borderWidth', fill = (point && point.color) || this.color,
  418. // set to fill when borderColor null:
  419. stroke = ((point && point[strokeOption]) ||
  420. options[strokeOption] ||
  421. this.color ||
  422. fill), strokeWidth = (point && point[strokeWidthOption]) ||
  423. options[strokeWidthOption] ||
  424. this[strokeWidthOption] || 0, dashstyle = (point && point.options.dashStyle) || options.dashStyle, opacity = pick(point && point.opacity, options.opacity, 1), zone, brightness;
  425. // Handle zone colors
  426. if (point && this.zones.length) {
  427. zone = point.getZone();
  428. // When zones are present, don't use point.color (#4267).
  429. // Changed order (#6527), added support for colorAxis (#10670)
  430. fill = (point.options.color ||
  431. (zone && (zone.color || point.nonZonedColor)) ||
  432. this.color);
  433. if (zone) {
  434. stroke = zone.borderColor || stroke;
  435. dashstyle = zone.dashStyle || dashstyle;
  436. strokeWidth = zone.borderWidth || strokeWidth;
  437. }
  438. }
  439. // Select or hover states
  440. if (state && point) {
  441. stateOptions = merge(options.states[state],
  442. // #6401
  443. point.options.states &&
  444. point.options.states[state] ||
  445. {});
  446. brightness = stateOptions.brightness;
  447. fill =
  448. stateOptions.color || (typeof brightness !== 'undefined' &&
  449. color(fill)
  450. .brighten(stateOptions.brightness)
  451. .get()) || fill;
  452. stroke = stateOptions[strokeOption] || stroke;
  453. strokeWidth =
  454. stateOptions[strokeWidthOption] || strokeWidth;
  455. dashstyle = stateOptions.dashStyle || dashstyle;
  456. opacity = pick(stateOptions.opacity, opacity);
  457. }
  458. ret = {
  459. fill: fill,
  460. stroke: stroke,
  461. 'stroke-width': strokeWidth,
  462. opacity: opacity
  463. };
  464. if (dashstyle) {
  465. ret.dashstyle = dashstyle;
  466. }
  467. return ret;
  468. };
  469. /**
  470. * Draw the columns. For bars, the series.group is rotated, so the same
  471. * coordinates apply for columns and bars. This method is inherited by
  472. * scatter series.
  473. *
  474. * @private
  475. * @function Highcharts.seriesTypes.column#drawPoints
  476. */
  477. ColumnSeries.prototype.drawPoints = function () {
  478. var series = this, chart = this.chart, options = series.options, renderer = chart.renderer, animationLimit = options.animationLimit || 250, shapeArgs;
  479. // draw the columns
  480. series.points.forEach(function (point) {
  481. var plotY = point.plotY, graphic = point.graphic, hasGraphic = !!graphic, verb = graphic && chart.pointCount < animationLimit ?
  482. 'animate' : 'attr';
  483. if (isNumber(plotY) && point.y !== null) {
  484. shapeArgs = point.shapeArgs;
  485. // When updating a series between 2d and 3d or cartesian and
  486. // polar, the shape type changes.
  487. if (graphic && point.hasNewShapeType()) {
  488. graphic = graphic.destroy();
  489. }
  490. // Set starting position for point sliding animation.
  491. if (series.enabledDataSorting) {
  492. point.startXPos = series.xAxis.reversed ?
  493. -(shapeArgs ? shapeArgs.width : 0) :
  494. series.xAxis.width;
  495. }
  496. if (!graphic) {
  497. point.graphic = graphic =
  498. renderer[point.shapeType](shapeArgs)
  499. .add(point.group || series.group);
  500. if (graphic &&
  501. series.enabledDataSorting &&
  502. chart.hasRendered &&
  503. chart.pointCount < animationLimit) {
  504. graphic.attr({
  505. x: point.startXPos
  506. });
  507. hasGraphic = true;
  508. verb = 'animate';
  509. }
  510. }
  511. if (graphic && hasGraphic) { // update
  512. graphic[verb](merge(shapeArgs));
  513. }
  514. // Border radius is not stylable (#6900)
  515. if (options.borderRadius) {
  516. graphic[verb]({
  517. r: options.borderRadius
  518. });
  519. }
  520. // Presentational
  521. if (!chart.styledMode) {
  522. graphic[verb](series.pointAttribs(point, (point.selected && 'select')))
  523. .shadow(point.allowShadow !== false && options.shadow, null, options.stacking && !options.borderRadius);
  524. }
  525. if (graphic) {
  526. graphic.addClass(point.getClassName(), true);
  527. graphic.attr({
  528. visibility: point.visible ? 'inherit' : 'hidden'
  529. });
  530. }
  531. }
  532. else if (graphic) {
  533. point.graphic = graphic.destroy(); // #1269
  534. }
  535. });
  536. };
  537. /**
  538. * Draw the tracker for a point.
  539. * @private
  540. */
  541. ColumnSeries.prototype.drawTracker = function () {
  542. var series = this, chart = series.chart, pointer = chart.pointer, onMouseOver = function (e) {
  543. var point = pointer.getPointFromEvent(e);
  544. // undefined on graph in scatterchart
  545. if (typeof point !== 'undefined') {
  546. pointer.isDirectTouch = true;
  547. point.onMouseOver(e);
  548. }
  549. }, dataLabels;
  550. // Add reference to the point
  551. series.points.forEach(function (point) {
  552. dataLabels = (isArray(point.dataLabels) ?
  553. point.dataLabels :
  554. (point.dataLabel ? [point.dataLabel] : []));
  555. if (point.graphic) {
  556. point.graphic.element.point = point;
  557. }
  558. dataLabels.forEach(function (dataLabel) {
  559. if (dataLabel.div) {
  560. dataLabel.div.point = point;
  561. }
  562. else {
  563. dataLabel.element.point = point;
  564. }
  565. });
  566. });
  567. // Add the event listeners, we need to do this only once
  568. if (!series._hasTracking) {
  569. series.trackerGroups.forEach(function (key) {
  570. if (series[key]) {
  571. // we don't always have dataLabelsGroup
  572. series[key]
  573. .addClass('highcharts-tracker')
  574. .on('mouseover', onMouseOver)
  575. .on('mouseout', function (e) {
  576. pointer.onTrackerMouseOut(e);
  577. });
  578. if (hasTouch) {
  579. series[key].on('touchstart', onMouseOver);
  580. }
  581. if (!chart.styledMode && series.options.cursor) {
  582. series[key]
  583. .css(css)
  584. .css({ cursor: series.options.cursor });
  585. }
  586. }
  587. });
  588. series._hasTracking = true;
  589. }
  590. fireEvent(this, 'afterDrawTracker');
  591. };
  592. /**
  593. * Remove this series from the chart
  594. *
  595. * @private
  596. * @function Highcharts.seriesTypes.column#remove
  597. */
  598. ColumnSeries.prototype.remove = function () {
  599. var series = this, chart = series.chart;
  600. // column and bar series affects other series of the same type
  601. // as they are either stacked or grouped
  602. if (chart.hasRendered) {
  603. chart.series.forEach(function (otherSeries) {
  604. if (otherSeries.type === series.type) {
  605. otherSeries.isDirty = true;
  606. }
  607. });
  608. }
  609. Series.prototype.remove.apply(series, arguments);
  610. };
  611. /**
  612. * Column series display one column per value along an X axis.
  613. *
  614. * @sample {highcharts} highcharts/demo/column-basic/
  615. * Column chart
  616. * @sample {highstock} stock/demo/column/
  617. * Column chart
  618. *
  619. * @extends plotOptions.line
  620. * @excluding connectEnds, connectNulls, gapSize, gapUnit, linecap,
  621. * lineWidth, marker, step, useOhlcData
  622. * @product highcharts highstock
  623. * @optionparent plotOptions.column
  624. */
  625. ColumnSeries.defaultOptions = merge(Series.defaultOptions, {
  626. /**
  627. * The corner radius of the border surrounding each column or bar.
  628. *
  629. * @sample {highcharts} highcharts/plotoptions/column-borderradius/
  630. * Rounded columns
  631. *
  632. * @product highcharts highstock gantt
  633. *
  634. * @private
  635. */
  636. borderRadius: 0,
  637. /**
  638. * When using automatic point colors pulled from the global
  639. * [colors](colors) or series-specific
  640. * [plotOptions.column.colors](series.colors) collections, this option
  641. * determines whether the chart should receive one color per series or
  642. * one color per point.
  643. *
  644. * In styled mode, the `colors` or `series.colors` arrays are not
  645. * supported, and instead this option gives the points individual color
  646. * class names on the form `highcharts-color-{n}`.
  647. *
  648. * @see [series colors](#plotOptions.column.colors)
  649. *
  650. * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-false/
  651. * False by default
  652. * @sample {highcharts} highcharts/plotoptions/column-colorbypoint-true/
  653. * True
  654. *
  655. * @type {boolean}
  656. * @default false
  657. * @since 2.0
  658. * @product highcharts highstock gantt
  659. * @apioption plotOptions.column.colorByPoint
  660. */
  661. /**
  662. * A series specific or series type specific color set to apply instead
  663. * of the global [colors](#colors) when [colorByPoint](
  664. * #plotOptions.column.colorByPoint) is true.
  665. *
  666. * @type {Array<Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject>}
  667. * @since 3.0
  668. * @product highcharts highstock gantt
  669. * @apioption plotOptions.column.colors
  670. */
  671. /**
  672. * When `true`, the columns will center in the category, ignoring null
  673. * or missing points. When `false`, space will be reserved for null or
  674. * missing points.
  675. *
  676. * @sample {highcharts} highcharts/series-column/centerincategory/
  677. * Center in category
  678. *
  679. * @since 8.0.1
  680. * @product highcharts highstock gantt
  681. *
  682. * @private
  683. */
  684. centerInCategory: false,
  685. /**
  686. * Padding between each value groups, in x axis units.
  687. *
  688. * @sample {highcharts} highcharts/plotoptions/column-grouppadding-default/
  689. * 0.2 by default
  690. * @sample {highcharts} highcharts/plotoptions/column-grouppadding-none/
  691. * No group padding - all columns are evenly spaced
  692. *
  693. * @product highcharts highstock gantt
  694. *
  695. * @private
  696. */
  697. groupPadding: 0.2,
  698. /**
  699. * Whether to group non-stacked columns or to let them render
  700. * independent of each other. Non-grouped columns will be laid out
  701. * individually and overlap each other.
  702. *
  703. * @sample {highcharts} highcharts/plotoptions/column-grouping-false/
  704. * Grouping disabled
  705. * @sample {highstock} highcharts/plotoptions/column-grouping-false/
  706. * Grouping disabled
  707. *
  708. * @type {boolean}
  709. * @default true
  710. * @since 2.3.0
  711. * @product highcharts highstock gantt
  712. * @apioption plotOptions.column.grouping
  713. */
  714. /**
  715. * @ignore-option
  716. * @private
  717. */
  718. marker: null,
  719. /**
  720. * The maximum allowed pixel width for a column, translated to the
  721. * height of a bar in a bar chart. This prevents the columns from
  722. * becoming too wide when there is a small number of points in the
  723. * chart.
  724. *
  725. * @see [pointWidth](#plotOptions.column.pointWidth)
  726. *
  727. * @sample {highcharts} highcharts/plotoptions/column-maxpointwidth-20/
  728. * Limited to 50
  729. * @sample {highstock} highcharts/plotoptions/column-maxpointwidth-20/
  730. * Limited to 50
  731. *
  732. * @type {number}
  733. * @since 4.1.8
  734. * @product highcharts highstock gantt
  735. * @apioption plotOptions.column.maxPointWidth
  736. */
  737. /**
  738. * Padding between each column or bar, in x axis units.
  739. *
  740. * @sample {highcharts} highcharts/plotoptions/column-pointpadding-default/
  741. * 0.1 by default
  742. * @sample {highcharts} highcharts/plotoptions/column-pointpadding-025/
  743. * 0.25
  744. * @sample {highcharts} highcharts/plotoptions/column-pointpadding-none/
  745. * 0 for tightly packed columns
  746. *
  747. * @product highcharts highstock gantt
  748. *
  749. * @private
  750. */
  751. pointPadding: 0.1,
  752. /**
  753. * A pixel value specifying a fixed width for each column or bar point.
  754. * When set to `undefined`, the width is calculated from the
  755. * `pointPadding` and `groupPadding`. The width effects the dimension
  756. * that is not based on the point value. For column series it is the
  757. * hoizontal length and for bar series it is the vertical length.
  758. *
  759. * @see [maxPointWidth](#plotOptions.column.maxPointWidth)
  760. *
  761. * @sample {highcharts} highcharts/plotoptions/column-pointwidth-20/
  762. * 20px wide columns regardless of chart width or the amount of
  763. * data points
  764. *
  765. * @type {number}
  766. * @since 1.2.5
  767. * @product highcharts highstock gantt
  768. * @apioption plotOptions.column.pointWidth
  769. */
  770. /**
  771. * A pixel value specifying a fixed width for the column or bar.
  772. * Overrides pointWidth on the series.
  773. *
  774. * @see [series.pointWidth](#plotOptions.column.pointWidth)
  775. *
  776. * @type {number}
  777. * @default undefined
  778. * @since 7.0.0
  779. * @product highcharts highstock gantt
  780. * @apioption series.column.data.pointWidth
  781. */
  782. /**
  783. * The minimal height for a column or width for a bar. By default,
  784. * 0 values are not shown. To visualize a 0 (or close to zero) point,
  785. * set the minimal point length to a pixel value like 3\. In stacked
  786. * column charts, minPointLength might not be respected for tightly
  787. * packed values.
  788. *
  789. * @sample {highcharts} highcharts/plotoptions/column-minpointlength/
  790. * Zero base value
  791. * @sample {highcharts} highcharts/plotoptions/column-minpointlength-pos-and-neg/
  792. * Positive and negative close to zero values
  793. *
  794. * @product highcharts highstock gantt
  795. *
  796. * @private
  797. */
  798. minPointLength: 0,
  799. /**
  800. * When the series contains less points than the crop threshold, all
  801. * points are drawn, event if the points fall outside the visible plot
  802. * area at the current zoom. The advantage of drawing all points
  803. * (including markers and columns), is that animation is performed on
  804. * updates. On the other hand, when the series contains more points than
  805. * the crop threshold, the series data is cropped to only contain points
  806. * that fall within the plot area. The advantage of cropping away
  807. * invisible points is to increase performance on large series.
  808. *
  809. * @product highcharts highstock gantt
  810. *
  811. * @private
  812. */
  813. cropThreshold: 50,
  814. /**
  815. * The X axis range that each point is valid for. This determines the
  816. * width of the column. On a categorized axis, the range will be 1
  817. * by default (one category unit). On linear and datetime axes, the
  818. * range will be computed as the distance between the two closest data
  819. * points.
  820. *
  821. * The default `null` means it is computed automatically, but this
  822. * option can be used to override the automatic value.
  823. *
  824. * This option is set by default to 1 if data sorting is enabled.
  825. *
  826. * @sample {highcharts} highcharts/plotoptions/column-pointrange/
  827. * Set the point range to one day on a data set with one week
  828. * between the points
  829. *
  830. * @type {number|null}
  831. * @since 2.3
  832. * @product highcharts highstock gantt
  833. *
  834. * @private
  835. */
  836. pointRange: null,
  837. states: {
  838. /**
  839. * Options for the hovered point. These settings override the normal
  840. * state options when a point is moused over or touched.
  841. *
  842. * @extends plotOptions.series.states.hover
  843. * @excluding halo, lineWidth, lineWidthPlus, marker
  844. * @product highcharts highstock gantt
  845. */
  846. hover: {
  847. /** @ignore-option */
  848. halo: false,
  849. /**
  850. * A specific border color for the hovered point. Defaults to
  851. * inherit the normal state border color.
  852. *
  853. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  854. * @product highcharts gantt
  855. * @apioption plotOptions.column.states.hover.borderColor
  856. */
  857. /**
  858. * A specific color for the hovered point.
  859. *
  860. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  861. * @product highcharts gantt
  862. * @apioption plotOptions.column.states.hover.color
  863. */
  864. /**
  865. * How much to brighten the point on interaction. Requires the
  866. * main color to be defined in hex or rgb(a) format.
  867. *
  868. * In styled mode, the hover brightening is by default replaced
  869. * with a fill-opacity set in the `.highcharts-point:hover`
  870. * rule.
  871. *
  872. * @sample {highcharts} highcharts/plotoptions/column-states-hover-brightness/
  873. * Brighten by 0.5
  874. *
  875. * @product highcharts highstock gantt
  876. */
  877. brightness: 0.1
  878. },
  879. /**
  880. * Options for the selected point. These settings override the
  881. * normal state options when a point is selected.
  882. *
  883. * @extends plotOptions.series.states.select
  884. * @excluding halo, lineWidth, lineWidthPlus, marker
  885. * @product highcharts highstock gantt
  886. */
  887. select: {
  888. /**
  889. * A specific color for the selected point.
  890. *
  891. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  892. * @default #cccccc
  893. * @product highcharts highstock gantt
  894. */
  895. color: palette.neutralColor20,
  896. /**
  897. * A specific border color for the selected point.
  898. *
  899. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  900. * @default #000000
  901. * @product highcharts highstock gantt
  902. */
  903. borderColor: palette.neutralColor100
  904. }
  905. },
  906. dataLabels: {
  907. align: void 0,
  908. verticalAlign: void 0,
  909. /**
  910. * The y position offset of the label relative to the point in
  911. * pixels.
  912. *
  913. * @type {number}
  914. */
  915. y: void 0
  916. },
  917. // false doesn't work well: https://jsfiddle.net/highcharts/hz8fopan/14/
  918. /**
  919. * @ignore-option
  920. * @private
  921. */
  922. startFromThreshold: true,
  923. stickyTracking: false,
  924. tooltip: {
  925. distance: 6
  926. },
  927. /**
  928. * The Y axis value to serve as the base for the columns, for
  929. * distinguishing between values above and below a threshold. If `null`,
  930. * the columns extend from the padding Y axis minimum.
  931. *
  932. * @type {number|null}
  933. * @since 2.0
  934. * @product highcharts
  935. *
  936. * @private
  937. */
  938. threshold: 0,
  939. /**
  940. * The width of the border surrounding each column or bar. Defaults to
  941. * `1` when there is room for a border, but to `0` when the columns are
  942. * so dense that a border would cover the next column.
  943. *
  944. * In styled mode, the stroke width can be set with the
  945. * `.highcharts-point` rule.
  946. *
  947. * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
  948. * 2px black border
  949. *
  950. * @type {number}
  951. * @default undefined
  952. * @product highcharts highstock gantt
  953. * @apioption plotOptions.column.borderWidth
  954. */
  955. /**
  956. * The color of the border surrounding each column or bar.
  957. *
  958. * In styled mode, the border stroke can be set with the
  959. * `.highcharts-point` rule.
  960. *
  961. * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
  962. * Dark gray border
  963. *
  964. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  965. * @default #ffffff
  966. * @product highcharts highstock gantt
  967. *
  968. * @private
  969. */
  970. borderColor: palette.backgroundColor
  971. });
  972. return ColumnSeries;
  973. }(Series));
  974. extend(ColumnSeries.prototype, {
  975. cropShoulder: 0,
  976. // When tooltip is not shared, this series (and derivatives) requires
  977. // direct touch/hover. KD-tree does not apply.
  978. directTouch: true,
  979. /**
  980. * Use a solid rectangle like the area series types
  981. *
  982. * @private
  983. * @function Highcharts.seriesTypes.column#drawLegendSymbol
  984. *
  985. * @param {Highcharts.Legend} legend
  986. * The legend object
  987. *
  988. * @param {Highcharts.Series|Highcharts.Point} item
  989. * The series (this) or point
  990. */
  991. drawLegendSymbol: LegendSymbolMixin.drawRectangle,
  992. getSymbol: noop,
  993. // use separate negative stacks, unlike area stacks where a negative
  994. // point is substracted from previous (#1910)
  995. negStacks: true,
  996. trackerGroups: ['group', 'dataLabelsGroup']
  997. });
  998. SeriesRegistry.registerSeriesType('column', ColumnSeries);
  999. /* *
  1000. *
  1001. * Export
  1002. *
  1003. * */
  1004. export default ColumnSeries;
  1005. /* *
  1006. *
  1007. * API Declarations
  1008. *
  1009. * */
  1010. /**
  1011. * Adjusted width and x offset of the columns for grouping.
  1012. *
  1013. * @private
  1014. * @interface Highcharts.ColumnMetricsObject
  1015. */ /**
  1016. * Width of the columns.
  1017. * @name Highcharts.ColumnMetricsObject#width
  1018. * @type {number}
  1019. */ /**
  1020. * Offset of the columns.
  1021. * @name Highcharts.ColumnMetricsObject#offset
  1022. * @type {number}
  1023. */
  1024. ''; // detach doclets above
  1025. /* *
  1026. *
  1027. * API Options
  1028. *
  1029. * */
  1030. /**
  1031. * A `column` series. If the [type](#series.column.type) option is
  1032. * not specified, it is inherited from [chart.type](#chart.type).
  1033. *
  1034. * @extends series,plotOptions.column
  1035. * @excluding connectNulls, dataParser, dataURL, gapSize, gapUnit, linecap,
  1036. * lineWidth, marker, connectEnds, step
  1037. * @product highcharts highstock
  1038. * @apioption series.column
  1039. */
  1040. /**
  1041. * An array of data points for the series. For the `column` series type,
  1042. * points can be given in the following ways:
  1043. *
  1044. * 1. An array of numerical values. In this case, the numerical values will be
  1045. * interpreted as `y` options. The `x` values will be automatically
  1046. * calculated, either starting at 0 and incremented by 1, or from
  1047. * `pointStart` and `pointInterval` given in the series options. If the axis
  1048. * has categories, these will be used. Example:
  1049. * ```js
  1050. * data: [0, 5, 3, 5]
  1051. * ```
  1052. *
  1053. * 2. An array of arrays with 2 values. In this case, the values correspond to
  1054. * `x,y`. If the first value is a string, it is applied as the name of the
  1055. * point, and the `x` value is inferred.
  1056. * ```js
  1057. * data: [
  1058. * [0, 6],
  1059. * [1, 2],
  1060. * [2, 6]
  1061. * ]
  1062. * ```
  1063. *
  1064. * 3. An array of objects with named values. The following snippet shows only a
  1065. * few settings, see the complete options set below. If the total number of
  1066. * data points exceeds the series'
  1067. * [turboThreshold](#series.column.turboThreshold), this option is not
  1068. * available.
  1069. * ```js
  1070. * data: [{
  1071. * x: 1,
  1072. * y: 9,
  1073. * name: "Point2",
  1074. * color: "#00FF00"
  1075. * }, {
  1076. * x: 1,
  1077. * y: 6,
  1078. * name: "Point1",
  1079. * color: "#FF00FF"
  1080. * }]
  1081. * ```
  1082. *
  1083. * @sample {highcharts} highcharts/chart/reflow-true/
  1084. * Numerical values
  1085. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  1086. * Arrays of numeric x and y
  1087. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  1088. * Arrays of datetime x and y
  1089. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  1090. * Arrays of point.name and y
  1091. * @sample {highcharts} highcharts/series/data-array-of-objects/
  1092. * Config objects
  1093. *
  1094. * @type {Array<number|Array<(number|string),(number|null)>|null|*>}
  1095. * @extends series.line.data
  1096. * @excluding marker
  1097. * @product highcharts highstock
  1098. * @apioption series.column.data
  1099. */
  1100. /**
  1101. * The color of the border surrounding the column or bar.
  1102. *
  1103. * In styled mode, the border stroke can be set with the `.highcharts-point`
  1104. * rule.
  1105. *
  1106. * @sample {highcharts} highcharts/plotoptions/column-bordercolor/
  1107. * Dark gray border
  1108. *
  1109. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  1110. * @product highcharts highstock
  1111. * @apioption series.column.data.borderColor
  1112. */
  1113. /**
  1114. * The width of the border surrounding the column or bar.
  1115. *
  1116. * In styled mode, the stroke width can be set with the `.highcharts-point`
  1117. * rule.
  1118. *
  1119. * @sample {highcharts} highcharts/plotoptions/column-borderwidth/
  1120. * 2px black border
  1121. *
  1122. * @type {number}
  1123. * @product highcharts highstock
  1124. * @apioption series.column.data.borderWidth
  1125. */
  1126. /**
  1127. * A name for the dash style to use for the column or bar. Overrides
  1128. * dashStyle on the series.
  1129. *
  1130. * In styled mode, the stroke dash-array can be set with the same classes as
  1131. * listed under [data.color](#series.column.data.color).
  1132. *
  1133. * @see [series.pointWidth](#plotOptions.column.dashStyle)
  1134. *
  1135. * @type {Highcharts.DashStyleValue}
  1136. * @apioption series.column.data.dashStyle
  1137. */
  1138. /**
  1139. * A pixel value specifying a fixed width for the column or bar. Overrides
  1140. * pointWidth on the series. The width effects the dimension that is not based
  1141. * on the point value.
  1142. *
  1143. * @see [series.pointWidth](#plotOptions.column.pointWidth)
  1144. *
  1145. * @type {number}
  1146. * @apioption series.column.data.pointWidth
  1147. */
  1148. /**
  1149. * @excluding halo, lineWidth, lineWidthPlus, marker
  1150. * @product highcharts highstock
  1151. * @apioption series.column.states.hover
  1152. */
  1153. /**
  1154. * @excluding halo, lineWidth, lineWidthPlus, marker
  1155. * @product highcharts highstock
  1156. * @apioption series.column.states.select
  1157. */
  1158. ''; // includes above doclets in transpilat