ControllablePath.js 4.9 KB

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