MarkerMixin.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* *
  2. *
  3. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  4. *
  5. * */
  6. 'use strict';
  7. import Chart from '../../../Core/Chart/Chart.js';
  8. import SVGRenderer from '../../../Core/Renderer/SVG/SVGRenderer.js';
  9. import U from '../../../Core/Utilities.js';
  10. var addEvent = U.addEvent, defined = U.defined, merge = U.merge, objectEach = U.objectEach, uniqueKey = U.uniqueKey;
  11. /**
  12. * Options for configuring markers for annotations.
  13. *
  14. * An example of the arrow marker:
  15. * <pre>
  16. * {
  17. * arrow: {
  18. * id: 'arrow',
  19. * tagName: 'marker',
  20. * refY: 5,
  21. * refX: 5,
  22. * markerWidth: 10,
  23. * markerHeight: 10,
  24. * children: [{
  25. * tagName: 'path',
  26. * attrs: {
  27. * d: 'M 0 0 L 10 5 L 0 10 Z',
  28. * strokeWidth: 0
  29. * }
  30. * }]
  31. * }
  32. * }
  33. * </pre>
  34. *
  35. * @sample highcharts/annotations/custom-markers/
  36. * Define a custom marker for annotations
  37. *
  38. * @sample highcharts/css/annotations-markers/
  39. * Define markers in a styled mode
  40. *
  41. * @type {Highcharts.Dictionary<Highcharts.SVGDefinitionObject>}
  42. * @since 6.0.0
  43. * @optionparent defs
  44. */
  45. var defaultMarkers = {
  46. /**
  47. * @type {Highcharts.SVGDefinitionObject}
  48. */
  49. arrow: {
  50. tagName: 'marker',
  51. render: false,
  52. id: 'arrow',
  53. refY: 5,
  54. refX: 9,
  55. markerWidth: 10,
  56. markerHeight: 10,
  57. /**
  58. * @type {Array<Highcharts.DefsOptions>}
  59. */
  60. children: [{
  61. tagName: 'path',
  62. d: 'M 0 0 L 10 5 L 0 10 Z',
  63. strokeWidth: 0
  64. }]
  65. },
  66. /**
  67. * @type {Highcharts.SVGDefinitionObject}
  68. */
  69. 'reverse-arrow': {
  70. tagName: 'marker',
  71. render: false,
  72. id: 'reverse-arrow',
  73. refY: 5,
  74. refX: 1,
  75. markerWidth: 10,
  76. markerHeight: 10,
  77. children: [{
  78. tagName: 'path',
  79. // reverse triangle (used as an arrow)
  80. d: 'M 0 5 L 10 0 L 10 10 Z',
  81. strokeWidth: 0
  82. }]
  83. }
  84. };
  85. SVGRenderer.prototype.addMarker = function (id, markerOptions) {
  86. var options = { id: id };
  87. var attrs = {
  88. stroke: markerOptions.color || 'none',
  89. fill: markerOptions.color || 'rgba(0, 0, 0, 0.75)'
  90. };
  91. options.children = markerOptions.children.map(function (child) {
  92. return merge(attrs, child);
  93. });
  94. var marker = this.definition(merge(true, {
  95. markerWidth: 20,
  96. markerHeight: 20,
  97. refX: 0,
  98. refY: 0,
  99. orient: 'auto'
  100. }, markerOptions, options));
  101. marker.id = id;
  102. return marker;
  103. };
  104. /* eslint-disable no-invalid-this, valid-jsdoc */
  105. /**
  106. * @private
  107. */
  108. function createMarkerSetter(markerType) {
  109. return function (value) {
  110. this.attr(markerType, 'url(#' + value + ')');
  111. };
  112. }
  113. /**
  114. * @private
  115. * @mixin
  116. * @name Highcharts.AnnotaitonMarkerMixin
  117. */
  118. var markerMixin = {
  119. markerEndSetter: createMarkerSetter('marker-end'),
  120. markerStartSetter: createMarkerSetter('marker-start'),
  121. /**
  122. * Set markers.
  123. * @private
  124. * @param {Highcharts.AnnotationControllablePath} item
  125. */
  126. setItemMarkers: function (item) {
  127. var itemOptions = item.options, chart = item.chart, defs = chart.options.defs, fill = itemOptions.fill, color = defined(fill) && fill !== 'none' ?
  128. fill :
  129. itemOptions.stroke, setMarker = function (markerType) {
  130. var markerId = itemOptions[markerType], def, predefinedMarker, key, marker;
  131. if (markerId) {
  132. for (key in defs) { // eslint-disable-line guard-for-in
  133. def = defs[key];
  134. if (markerId === def.id &&
  135. def.tagName === 'marker') {
  136. predefinedMarker = def;
  137. break;
  138. }
  139. }
  140. if (predefinedMarker) {
  141. marker = item[markerType] = chart.renderer
  142. .addMarker((itemOptions.id || uniqueKey()) + '-' +
  143. predefinedMarker.id, merge(predefinedMarker, { color: color }));
  144. item.attr(markerType, marker.attr('id'));
  145. }
  146. }
  147. };
  148. ['markerStart', 'markerEnd'].forEach(setMarker);
  149. }
  150. };
  151. addEvent(Chart, 'afterGetContainer', function () {
  152. this.options.defs = merge(defaultMarkers, this.options.defs || {});
  153. objectEach(this.options.defs, function (def) {
  154. if (def.tagName === 'marker' && def.render !== false) {
  155. this.renderer.addMarker(def.id, def);
  156. }
  157. }, this);
  158. });
  159. export default markerMixin;