ControllablePath.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. 'use strict';
  2. import H from './../../parts/Globals.js';
  3. import './../../parts/Utilities.js';
  4. import controllableMixin from './controllableMixin.js';
  5. import markerMixin from './markerMixin.js';
  6. // See TRACKER_FILL in highcharts.src.js
  7. var TRACKER_FILL = 'rgba(192,192,192,' + (H.svg ? 0.0001 : 0.002) + ')';
  8. /**
  9. * A controllable path class.
  10. *
  11. * @class
  12. * @mixes Annotation.controllableMixin
  13. * @mixes Annotation.markerMixin
  14. * @memberOf Annotation
  15. *
  16. * @param {Highcharts.Annotation}
  17. * @param {Object} options a path's options object
  18. * @param {number} index of the path
  19. **/
  20. function ControllablePath(annotation, options, index) {
  21. this.init(annotation, options, index);
  22. this.collection = 'shapes';
  23. }
  24. /**
  25. * @typedef {Object} Annotation.ControllablePath.AttrsMap
  26. * @property {string} dashStyle=dashstyle
  27. * @property {string} strokeWidth=stroke-width
  28. * @property {string} stroke=stroke
  29. * @property {string} fill=fill
  30. * @property {string} zIndex=zIndex
  31. */
  32. /**
  33. * A map object which allows to map options attributes to element attributes
  34. *
  35. * @type {Annotation.ControllablePath.AttrsMap}
  36. */
  37. ControllablePath.attrsMap = {
  38. dashStyle: 'dashstyle',
  39. strokeWidth: 'stroke-width',
  40. stroke: 'stroke',
  41. fill: 'fill',
  42. zIndex: 'zIndex'
  43. };
  44. H.merge(
  45. true,
  46. ControllablePath.prototype,
  47. controllableMixin, /** @lends Annotation.ControllablePath# */ {
  48. /**
  49. * @type 'path'
  50. */
  51. type: 'path',
  52. setMarkers: markerMixin.setItemMarkers,
  53. /**
  54. * Map the controllable path to 'd' path attribute
  55. *
  56. * @return {Array<(string|number)>} a path's d attribute
  57. */
  58. toD: function () {
  59. var d = this.options.d;
  60. if (d) {
  61. return typeof d === 'function' ?
  62. d.call(this) :
  63. d;
  64. }
  65. var points = this.points,
  66. len = points.length,
  67. showPath = len,
  68. point = points[0],
  69. position = showPath && this.anchor(point).absolutePosition,
  70. pointIndex = 0,
  71. dIndex = 2,
  72. command;
  73. d = position && ['M', position.x, position.y];
  74. while (++pointIndex < len && showPath) {
  75. point = points[pointIndex];
  76. command = point.command || 'L';
  77. position = this.anchor(point).absolutePosition;
  78. if (command === 'Z') {
  79. d[++dIndex] = command;
  80. } else {
  81. if (command !== points[pointIndex - 1].command) {
  82. d[++dIndex] = command;
  83. }
  84. d[++dIndex] = position.x;
  85. d[++dIndex] = position.y;
  86. }
  87. showPath = point.series.visible;
  88. }
  89. return showPath ?
  90. this.chart.renderer.crispLine(d, this.graphic.strokeWidth()) :
  91. null;
  92. },
  93. shouldBeDrawn: function () {
  94. return controllableMixin.shouldBeDrawn.call(this) ||
  95. Boolean(this.options.d);
  96. },
  97. render: function (parent) {
  98. var options = this.options,
  99. attrs = this.attrsFromOptions(options);
  100. this.graphic = this.annotation.chart.renderer
  101. .path(['M', 0, 0])
  102. .attr(attrs)
  103. .add(parent);
  104. if (options.className) {
  105. this.graphic.addClass(options.className);
  106. }
  107. this.tracker = this.annotation.chart.renderer
  108. .path(['M', 0, 0])
  109. .addClass('highcharts-tracker-line')
  110. .attr({
  111. zIndex: 2
  112. })
  113. .add(parent);
  114. if (!this.annotation.chart.styledMode) {
  115. this.tracker.attr({
  116. 'stroke-linejoin': 'round', // #1225
  117. stroke: TRACKER_FILL,
  118. fill: TRACKER_FILL,
  119. 'stroke-width': this.graphic.strokeWidth() +
  120. options.snap * 2
  121. });
  122. }
  123. controllableMixin.render.call(this);
  124. H.extend(this.graphic, {
  125. markerStartSetter: markerMixin.markerStartSetter,
  126. markerEndSetter: markerMixin.markerEndSetter
  127. });
  128. this.setMarkers(this);
  129. },
  130. redraw: function (animation) {
  131. var d = this.toD(),
  132. action = animation ? 'animate' : 'attr';
  133. if (d) {
  134. this.graphic[action]({ d: d });
  135. this.tracker[action]({ d: d });
  136. } else {
  137. this.graphic.attr({ d: 'M 0 ' + -9e9 });
  138. this.tracker.attr({ d: 'M 0 ' + -9e9 });
  139. }
  140. this.graphic.placed = this.tracker.placed = Boolean(d);
  141. controllableMixin.redraw.call(this, animation);
  142. }
  143. }
  144. );
  145. export default ControllablePath;