ColumnSeries.js 37 KB

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