ColumnSeries.js 40 KB

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