dumbbell.src.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /* *
  2. *
  3. * (c) 2010-2019 Sebastian Bochan, Rafal Sebestjanski
  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 '../parts/Globals.js';
  12. var pick = H.pick, seriesType = H.seriesType, seriesTypes = H.seriesTypes, seriesProto = H.Series.prototype, areaRangeProto = seriesTypes.arearange.prototype, columnRangeProto = seriesTypes.columnrange.prototype, colProto = seriesTypes.column.prototype, areaRangePointProto = areaRangeProto.pointClass.prototype;
  13. /**
  14. * The dumbbell series is a cartesian series with higher and lower values for
  15. * each point along an X axis, connected with a line between the values.
  16. * Requires `highcharts-more.js` and `modules/dumbbell.js`.
  17. *
  18. * @sample {highcharts} highcharts/demo/dumbbell/
  19. * Dumbbell chart
  20. * @sample {highcharts} highcharts/series-dumbbell/styled-mode-dumbbell/
  21. * Styled mode
  22. *
  23. * @extends plotOptions.arearange
  24. * @product highcharts highstock
  25. * @excluding fillColor, fillOpacity, lineWidth, stack, stacking,
  26. * stickyTracking, trackByArea
  27. * @since 8.0.0
  28. * @optionparent plotOptions.dumbbell
  29. */
  30. seriesType('dumbbell', 'arearange', {
  31. /** @ignore-option */
  32. trackByArea: false,
  33. /** @ignore-option */
  34. fillColor: 'none',
  35. /** @ignore-option */
  36. lineWidth: 0,
  37. pointRange: 1,
  38. /**
  39. * Pixel width of the line that connects the dumbbell point's values.
  40. *
  41. * @since 8.0.0
  42. * @product highcharts highstock
  43. */
  44. connectorWidth: 1,
  45. /** @ignore-option */
  46. stickyTracking: false,
  47. groupPadding: 0.2,
  48. pointPadding: 0.1,
  49. /**
  50. * Color of the start markers in a dumbbell graph.
  51. *
  52. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  53. * @since 8.0.0
  54. * @product highcharts highstock
  55. */
  56. lowColor: '#333333',
  57. /**
  58. * Color of the line that connects the dumbbell point's values.
  59. * By default it is the series' color.
  60. *
  61. * @type {string}
  62. * @product highcharts highstock
  63. * @since 8.0.0
  64. * @apioption plotOptions.dumbbell.connectorColor
  65. */
  66. states: {
  67. hover: {
  68. /** @ignore-option */
  69. lineWidthPlus: 0,
  70. /**
  71. * The additional connector line width for a hovered point.
  72. *
  73. * @since 8.0.0
  74. * @product highcharts highstock
  75. */
  76. connectorWidthPlus: 1,
  77. /** @ignore-option */
  78. halo: false
  79. }
  80. }
  81. }, {
  82. trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
  83. drawTracker: H.TrackerMixin.drawTrackerPoint,
  84. drawGraph: H.noop,
  85. /**
  86. * Correct line position by Math.floor instead of round.
  87. * As a result the line is aligned in the same way as marker
  88. *
  89. * @private
  90. *
  91. * @function Highcharts.seriesTypes.dumbbell#crispConnector
  92. *
  93. * @param {Highcharts.SVGRenderer} this
  94. * Highcharts Renderer.
  95. * @param {Highcharts.SVGPathArray} points
  96. * The original points on the format `['M', 0, 0, 'L', 100, 0]`.
  97. * @param {number} width
  98. * Connector's width.
  99. *
  100. * @return {Highcharts.SVGPathArray}
  101. * The original points array, but modified to render crisply.
  102. *
  103. *
  104. */
  105. crispConnector: function (points, width) {
  106. if (points[1] === points[4]) {
  107. // Substract due to #1129. Now bottom and left axis gridlines behave
  108. // the same.
  109. points[1] = points[4] =
  110. Math.floor(points[1]) + (width % 2 / 2);
  111. }
  112. if (points[2] === points[5]) {
  113. points[2] = points[5] =
  114. Math.floor(points[2]) + (width % 2 / 2);
  115. }
  116. return points;
  117. },
  118. crispCol: colProto.crispCol,
  119. /**
  120. * Get connector line path and styles that connects dumbbell point's low and
  121. * high values.
  122. * @private
  123. *
  124. * @param {Highcharts.Series} this The series of points.
  125. * @param {Highcharts.Point} point The point to inspect.
  126. *
  127. * @return {Highcharts.SVGAttributes} attribs The path and styles.
  128. */
  129. getConnectorAttribs: function (point) {
  130. var series = this, chart = series.chart, pointOptions = point.options, seriesOptions = series.options, xAxis = series.xAxis, yAxis = series.yAxis, connectorWidth = pick(pointOptions.connectorWidth, seriesOptions.connectorWidth), connectorColor = pick(pointOptions.connectorColor, seriesOptions.connectorColor, pointOptions.color, point.zone ? point.zone.color : void 0, point.color), connectorWidthPlus = pick(seriesOptions.states &&
  131. seriesOptions.states.hover &&
  132. seriesOptions.states.hover.connectorWidthPlus, 1), dashStyle = pick(pointOptions.dashStyle, seriesOptions.dashStyle), pointTop = pick(point.plotLow, point.plotY), pxThreshold = yAxis.toPixels(seriesOptions.threshold || 0, true), pointHeight = chart.inverted ?
  133. yAxis.len - pxThreshold : pxThreshold, pointBottom = pick(point.plotHigh, pointHeight), attribs, origProps;
  134. if (point.state) {
  135. connectorWidth = connectorWidth + connectorWidthPlus;
  136. }
  137. if (pointTop < 0) {
  138. pointTop = 0;
  139. }
  140. else if (pointTop >= yAxis.len) {
  141. pointTop = yAxis.len;
  142. }
  143. if (pointBottom < 0) {
  144. pointBottom = 0;
  145. }
  146. else if (pointBottom >= yAxis.len) {
  147. pointBottom = yAxis.len;
  148. }
  149. if (point.plotX < 0 || point.plotX > xAxis.len) {
  150. connectorWidth = 0;
  151. }
  152. // Connector should reflect upper marker's zone color
  153. if (point.upperGraphic) {
  154. origProps = {
  155. y: point.y,
  156. zone: point.zone
  157. };
  158. point.y = point.high;
  159. point.zone = point.zone ? point.getZone() : void 0;
  160. connectorColor = pick(pointOptions.connectorColor, seriesOptions.connectorColor, pointOptions.color, point.zone ? point.zone.color : void 0, point.color);
  161. H.extend(point, origProps);
  162. }
  163. attribs = {
  164. d: series.crispConnector([
  165. 'M',
  166. point.plotX,
  167. pointTop,
  168. 'L',
  169. point.plotX,
  170. pointBottom
  171. ], connectorWidth)
  172. };
  173. if (!chart.styledMode) {
  174. attribs.stroke = connectorColor;
  175. attribs['stroke-width'] = connectorWidth;
  176. if (dashStyle) {
  177. attribs.dashstyle = dashStyle;
  178. }
  179. }
  180. return attribs;
  181. },
  182. /**
  183. * Draw connector line that connects dumbbell point's low and high values.
  184. * @private
  185. *
  186. * @param {Highcharts.Series} this The series of points.
  187. * @param {Highcharts.Point} point The point to inspect.
  188. *
  189. * @return {void}
  190. */
  191. drawConnector: function (point) {
  192. var series = this, animationLimit = pick(series.options.animationLimit, 250), verb = point.connector && series.chart.pointCount < animationLimit ?
  193. 'animate' : 'attr';
  194. if (!point.connector) {
  195. point.connector = series.chart.renderer.path()
  196. .addClass('highcharts-lollipop-stem')
  197. .attr({
  198. zIndex: -1
  199. })
  200. .add(series.markerGroup);
  201. }
  202. point.connector[verb](this.getConnectorAttribs(point));
  203. },
  204. /**
  205. * Return the width and x offset of the dumbbell adjusted for grouping,
  206. * groupPadding, pointPadding, pointWidth etc.
  207. *
  208. * @private
  209. *
  210. * @function Highcharts.seriesTypes.column#getColumnMetrics
  211. *
  212. * @param {Highcharts.Series} this The series of points.
  213. *
  214. * @return {Highcharts.ColumnMetricsObject} metrics shapeArgs
  215. *
  216. */
  217. getColumnMetrics: function () {
  218. var metrics = colProto.getColumnMetrics.apply(this, arguments);
  219. metrics.offset = metrics.offset + metrics.width / 2;
  220. return metrics;
  221. },
  222. translatePoint: areaRangeProto.translate,
  223. setShapeArgs: columnRangeProto.translate,
  224. /**
  225. * Translate each point to the plot area coordinate system and find
  226. * shape positions
  227. *
  228. * @private
  229. *
  230. * @function Highcharts.seriesTypes.dumbbell#translate
  231. *
  232. * @param {Highcharts.Series} this The series of points.
  233. *
  234. * @return {void}
  235. */
  236. translate: function () {
  237. // Calculate shapeargs
  238. this.setShapeArgs.apply(this);
  239. // Calculate point low / high values
  240. this.translatePoint.apply(this, arguments);
  241. // Correct x position
  242. this.points.forEach(function (point) {
  243. var shapeArgs = point.shapeArgs, pointWidth = point.pointWidth;
  244. point.plotX = shapeArgs.x;
  245. shapeArgs.x = point.plotX - pointWidth / 2;
  246. point.tooltipPos = null;
  247. });
  248. },
  249. seriesDrawPoints: areaRangeProto.drawPoints,
  250. /**
  251. * Extend the arearange series' drawPoints method by applying a connector
  252. * and coloring markers.
  253. * @private
  254. *
  255. * @function Highcharts.Series#drawPoints
  256. *
  257. * @param {Highcharts.Series} this The series of points.
  258. *
  259. * @return {void}
  260. */
  261. drawPoints: function () {
  262. var series = this, chart = series.chart, pointLength = series.points.length, seriesLowColor = series.lowColor = series.options.lowColor, i = 0, lowerGraphicColor, point, zoneColor;
  263. this.seriesDrawPoints.apply(series, arguments);
  264. // Draw connectors and color upper markers
  265. while (i < pointLength) {
  266. point = series.points[i];
  267. series.drawConnector(point);
  268. if (point.upperGraphic) {
  269. point.upperGraphic.element.point = point;
  270. point.upperGraphic.addClass('highcharts-lollipop-high');
  271. }
  272. point.connector.element.point = point;
  273. if (point.lowerGraphic) {
  274. zoneColor = point.zone && point.zone.color;
  275. lowerGraphicColor = pick(point.options.lowColor, seriesLowColor, point.options.color, zoneColor, point.color, series.color);
  276. if (!chart.styledMode) {
  277. point.lowerGraphic.attr({
  278. fill: lowerGraphicColor
  279. });
  280. }
  281. point.lowerGraphic.addClass('highcharts-lollipop-low');
  282. }
  283. i++;
  284. }
  285. },
  286. /**
  287. * Get non-presentational attributes for a point. Used internally for
  288. * both styled mode and classic. Set correct position in link with connector
  289. * line.
  290. *
  291. * @see Series#pointAttribs
  292. *
  293. * @function Highcharts.Series#markerAttribs
  294. *
  295. * @param {Highcharts.Series} this The series of points.
  296. *
  297. * @return {Highcharts.SVGAttributes}
  298. * A hash containing those attributes that are not settable from
  299. * CSS.
  300. */
  301. markerAttribs: function () {
  302. var ret = areaRangeProto.markerAttribs.apply(this, arguments);
  303. ret.x = Math.floor(ret.x);
  304. ret.y = Math.floor(ret.y);
  305. return ret;
  306. },
  307. /**
  308. * Get presentational attributes
  309. *
  310. * @private
  311. * @function Highcharts.seriesTypes.column#pointAttribs
  312. *
  313. * @param {Highcharts.Series} this The series of points.
  314. * @param {Highcharts.Point} point The point to inspect.
  315. * @param {string} state current state of point (normal, hover, select)
  316. *
  317. * @return {Highcharts.SVGAttributes} pointAttribs SVGAttributes
  318. */
  319. pointAttribs: function (point, state) {
  320. var pointAttribs;
  321. pointAttribs = seriesProto.pointAttribs.apply(this, arguments);
  322. if (state === 'hover') {
  323. delete pointAttribs.fill;
  324. }
  325. return pointAttribs;
  326. }
  327. }, {
  328. // seriesTypes doesn't inherit from arearange point proto so put below
  329. // methods rigidly.
  330. destroyElements: areaRangePointProto.destroyElements,
  331. isValid: areaRangePointProto.isValid,
  332. pointSetState: areaRangePointProto.setState,
  333. /**
  334. * Set the point's state extended by have influence on the connector
  335. * (between low and high value).
  336. *
  337. * @private
  338. * @param {Highcharts.Point} this The point to inspect.
  339. *
  340. * @return {void}
  341. */
  342. setState: function () {
  343. var point = this, series = point.series, chart = series.chart, seriesLowColor = series.options.lowColor, pointOptions = point.options, pointLowColor = pointOptions.lowColor, zoneColor = point.zone && point.zone.color, lowerGraphicColor = pick(pointLowColor, seriesLowColor, pointOptions.color, zoneColor, point.color, series.color), verb = 'attr', upperGraphicColor, origProps;
  344. this.pointSetState.apply(this, arguments);
  345. if (!this.state) {
  346. verb = 'animate';
  347. if (point.lowerGraphic && !chart.styledMode) {
  348. point.lowerGraphic.attr({
  349. fill: lowerGraphicColor
  350. });
  351. if (point.upperGraphic) {
  352. origProps = {
  353. y: point.y,
  354. zone: point.zone
  355. };
  356. point.y = point.high;
  357. point.zone = point.zone ? point.getZone() : void 0;
  358. upperGraphicColor = pick(point.marker ? point.marker.fillColor : void 0, pointOptions.color, point.zone ? point.zone.color : void 0, point.color);
  359. point.upperGraphic.attr({
  360. fill: upperGraphicColor
  361. });
  362. H.extend(point, origProps);
  363. }
  364. }
  365. }
  366. point.connector[verb](series.getConnectorAttribs(point));
  367. }
  368. });