SplineSeries.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /* *
  2. *
  3. * (c) 2010-2021 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. var __extends = (this && this.__extends) || (function () {
  12. var extendStatics = function (d, b) {
  13. extendStatics = Object.setPrototypeOf ||
  14. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  15. function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
  16. return extendStatics(d, b);
  17. };
  18. return function (d, b) {
  19. extendStatics(d, b);
  20. function __() { this.constructor = d; }
  21. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  22. };
  23. })();
  24. import SeriesRegistry from '../../Core/Series/SeriesRegistry.js';
  25. var LineSeries = SeriesRegistry.seriesTypes.line;
  26. import U from '../../Core/Utilities.js';
  27. var merge = U.merge, pick = U.pick;
  28. /**
  29. * Spline series type.
  30. *
  31. * @private
  32. */
  33. var SplineSeries = /** @class */ (function (_super) {
  34. __extends(SplineSeries, _super);
  35. function SplineSeries() {
  36. /* *
  37. *
  38. * Static Properties
  39. *
  40. * */
  41. var _this = _super !== null && _super.apply(this, arguments) || this;
  42. /* *
  43. *
  44. * Properties
  45. *
  46. * */
  47. _this.data = void 0;
  48. _this.options = void 0;
  49. _this.points = void 0;
  50. return _this;
  51. /* eslint-enable valid-jsdoc */
  52. }
  53. /* *
  54. *
  55. * Functions
  56. *
  57. * */
  58. /* eslint-disable valid-jsdoc */
  59. /**
  60. * Get the spline segment from a given point's previous neighbour to the
  61. * given point.
  62. *
  63. * @private
  64. * @function Highcharts.seriesTypes.spline#getPointSpline
  65. *
  66. * @param {Array<Highcharts.Point>}
  67. *
  68. * @param {Highcharts.Point} point
  69. *
  70. * @param {number} i
  71. *
  72. * @return {Highcharts.SVGPathArray}
  73. */
  74. SplineSeries.prototype.getPointSpline = function (points, point, i) {
  75. var
  76. // 1 means control points midway between points, 2 means 1/3
  77. // from the point, 3 is 1/4 etc
  78. smoothing = 1.5, denom = smoothing + 1, plotX = point.plotX || 0, plotY = point.plotY || 0, lastPoint = points[i - 1], nextPoint = points[i + 1], leftContX, leftContY, rightContX, rightContY, ret;
  79. /**
  80. * @private
  81. */
  82. function doCurve(otherPoint) {
  83. return otherPoint &&
  84. !otherPoint.isNull &&
  85. otherPoint.doCurve !== false &&
  86. // #6387, area splines next to null:
  87. !point.isCliff;
  88. }
  89. // Find control points
  90. if (doCurve(lastPoint) && doCurve(nextPoint)) {
  91. var lastX = lastPoint.plotX || 0, lastY = lastPoint.plotY || 0, nextX = nextPoint.plotX || 0, nextY = nextPoint.plotY || 0, correction = 0;
  92. leftContX = (smoothing * plotX + lastX) / denom;
  93. leftContY = (smoothing * plotY + lastY) / denom;
  94. rightContX = (smoothing * plotX + nextX) / denom;
  95. rightContY = (smoothing * plotY + nextY) / denom;
  96. // Have the two control points make a straight line through main
  97. // point
  98. if (rightContX !== leftContX) { // #5016, division by zero
  99. correction = (((rightContY - leftContY) *
  100. (rightContX - plotX)) /
  101. (rightContX - leftContX) + plotY - rightContY);
  102. }
  103. leftContY += correction;
  104. rightContY += correction;
  105. // to prevent false extremes, check that control points are
  106. // between neighbouring points' y values
  107. if (leftContY > lastY && leftContY > plotY) {
  108. leftContY = Math.max(lastY, plotY);
  109. // mirror of left control point
  110. rightContY = 2 * plotY - leftContY;
  111. }
  112. else if (leftContY < lastY && leftContY < plotY) {
  113. leftContY = Math.min(lastY, plotY);
  114. rightContY = 2 * plotY - leftContY;
  115. }
  116. if (rightContY > nextY && rightContY > plotY) {
  117. rightContY = Math.max(nextY, plotY);
  118. leftContY = 2 * plotY - rightContY;
  119. }
  120. else if (rightContY < nextY && rightContY < plotY) {
  121. rightContY = Math.min(nextY, plotY);
  122. leftContY = 2 * plotY - rightContY;
  123. }
  124. // record for drawing in next point
  125. point.rightContX = rightContX;
  126. point.rightContY = rightContY;
  127. }
  128. // Visualize control points for debugging
  129. /*
  130. if (leftContX) {
  131. this.chart.renderer.circle(
  132. leftContX + this.chart.plotLeft,
  133. leftContY + this.chart.plotTop,
  134. 2
  135. )
  136. .attr({
  137. stroke: 'red',
  138. 'stroke-width': 2,
  139. fill: 'none',
  140. zIndex: 9
  141. })
  142. .add();
  143. this.chart.renderer.path(['M', leftContX + this.chart.plotLeft,
  144. leftContY + this.chart.plotTop,
  145. 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
  146. .attr({
  147. stroke: 'red',
  148. 'stroke-width': 2,
  149. zIndex: 9
  150. })
  151. .add();
  152. }
  153. if (rightContX) {
  154. this.chart.renderer.circle(
  155. rightContX + this.chart.plotLeft,
  156. rightContY + this.chart.plotTop,
  157. 2
  158. )
  159. .attr({
  160. stroke: 'green',
  161. 'stroke-width': 2,
  162. fill: 'none',
  163. zIndex: 9
  164. })
  165. .add();
  166. this.chart.renderer.path(['M', rightContX + this.chart.plotLeft,
  167. rightContY + this.chart.plotTop,
  168. 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop])
  169. .attr({
  170. stroke: 'green',
  171. 'stroke-width': 2,
  172. zIndex: 9
  173. })
  174. .add();
  175. }
  176. // */
  177. ret = [
  178. 'C',
  179. pick(lastPoint.rightContX, lastPoint.plotX, 0),
  180. pick(lastPoint.rightContY, lastPoint.plotY, 0),
  181. pick(leftContX, plotX, 0),
  182. pick(leftContY, plotY, 0),
  183. plotX,
  184. plotY
  185. ];
  186. // reset for updating series later
  187. lastPoint.rightContX = lastPoint.rightContY = void 0;
  188. return ret;
  189. };
  190. /**
  191. * A spline series is a special type of line series, where the segments
  192. * between the data points are smoothed.
  193. *
  194. * @sample {highcharts} highcharts/demo/spline-irregular-time/
  195. * Spline chart
  196. * @sample {highstock} stock/demo/spline/
  197. * Spline chart
  198. *
  199. * @extends plotOptions.series
  200. * @excluding step, boostThreshold, boostBlending
  201. * @product highcharts highstock
  202. * @optionparent plotOptions.spline
  203. */
  204. SplineSeries.defaultOptions = merge(LineSeries.defaultOptions);
  205. return SplineSeries;
  206. }(LineSeries));
  207. SeriesRegistry.registerSeriesType('spline', SplineSeries);
  208. /* *
  209. *
  210. * Default Export
  211. *
  212. * */
  213. export default SplineSeries;
  214. /* *
  215. *
  216. * API Options
  217. *
  218. * */
  219. /**
  220. * A `spline` series. If the [type](#series.spline.type) option is
  221. * not specified, it is inherited from [chart.type](#chart.type).
  222. *
  223. * @extends series,plotOptions.spline
  224. * @excluding dataParser, dataURL, step, boostThreshold, boostBlending
  225. * @product highcharts highstock
  226. * @apioption series.spline
  227. */
  228. /**
  229. * An array of data points for the series. For the `spline` series type,
  230. * points can be given in the following ways:
  231. *
  232. * 1. An array of numerical values. In this case, the numerical values will be
  233. * interpreted as `y` options. The `x` values will be automatically
  234. * calculated, either starting at 0 and incremented by 1, or from
  235. * `pointStart` and `pointInterval` given in the series options. If the axis
  236. * has categories, these will be used. Example:
  237. * ```js
  238. * data: [0, 5, 3, 5]
  239. * ```
  240. *
  241. * 2. An array of arrays with 2 values. In this case, the values correspond to
  242. * `x,y`. If the first value is a string, it is applied as the name of the
  243. * point, and the `x` value is inferred.
  244. * ```js
  245. * data: [
  246. * [0, 9],
  247. * [1, 2],
  248. * [2, 8]
  249. * ]
  250. * ```
  251. *
  252. * 3. An array of objects with named values. The following snippet shows only a
  253. * few settings, see the complete options set below. If the total number of
  254. * data points exceeds the series'
  255. * [turboThreshold](#series.spline.turboThreshold),
  256. * this option is not available.
  257. * ```js
  258. * data: [{
  259. * x: 1,
  260. * y: 9,
  261. * name: "Point2",
  262. * color: "#00FF00"
  263. * }, {
  264. * x: 1,
  265. * y: 0,
  266. * name: "Point1",
  267. * color: "#FF00FF"
  268. * }]
  269. * ```
  270. *
  271. * @sample {highcharts} highcharts/chart/reflow-true/
  272. * Numerical values
  273. * @sample {highcharts} highcharts/series/data-array-of-arrays/
  274. * Arrays of numeric x and y
  275. * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/
  276. * Arrays of datetime x and y
  277. * @sample {highcharts} highcharts/series/data-array-of-name-value/
  278. * Arrays of point.name and y
  279. * @sample {highcharts} highcharts/series/data-array-of-objects/
  280. * Config objects
  281. *
  282. * @type {Array<number|Array<(number|string),(number|null)>|null|*>}
  283. * @extends series.line.data
  284. * @product highcharts highstock
  285. * @apioption series.spline.data
  286. */
  287. ''; // adds doclets above intro transpilat