elementSelect.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. "use strict";
  2. var __rest = (this && this.__rest) || function (s, e) {
  3. var t = {};
  4. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  5. t[p] = s[p];
  6. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  7. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  8. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  9. t[p[i]] = s[p[i]];
  10. }
  11. return t;
  12. };
  13. Object.defineProperty(exports, "__esModule", { value: true });
  14. exports.ElementSelect = exports.elementSelect = void 0;
  15. const d3_array_1 = require("d3-array");
  16. const util_1 = require("@antv/util");
  17. const helper_1 = require("../utils/helper");
  18. const utils_1 = require("./utils");
  19. /**
  20. * Active a group of elements.
  21. */
  22. function elementSelect(root, { elements: elementsof, // given the root of chart returns elements to be manipulated
  23. datum, // given each element returns the datum of it
  24. groupKey = (d) => d, // group elements by specified key
  25. link = false, // draw link or not
  26. single = false, // single select or not
  27. coordinate, background = false, scale, emitter, state = {}, }) {
  28. var _a;
  29. const elements = elementsof(root);
  30. const elementSet = new Set(elements);
  31. const keyGroup = (0, d3_array_1.group)(elements, groupKey);
  32. const valueof = (0, utils_1.createValueof)(elements, datum);
  33. const [appendLink, removeLink] = (0, utils_1.renderLink)(Object.assign({ link,
  34. elements,
  35. valueof,
  36. coordinate }, (0, helper_1.subObject)(state.selected, 'link')));
  37. const [appendBackground, removeBackground] = (0, utils_1.renderBackground)(Object.assign({ background,
  38. coordinate,
  39. scale,
  40. valueof }, (0, helper_1.subObject)(state.selected, 'background')));
  41. const elementStyle = (0, util_1.deepMix)(state, {
  42. selected: Object.assign({}, (((_a = state.selected) === null || _a === void 0 ? void 0 : _a.offset) && {
  43. //Apply translate to mock slice out.
  44. transform: (...params) => {
  45. const value = state.selected.offset(...params);
  46. const [, i] = params;
  47. return (0, utils_1.offsetTransform)(elements[i], value, coordinate);
  48. },
  49. })),
  50. });
  51. const { setState, removeState, hasState } = (0, utils_1.useState)(elementStyle, valueof);
  52. const clear = (nativeEvent = true) => {
  53. for (const e of elements) {
  54. removeState(e, 'selected', 'unselected');
  55. removeLink(e);
  56. removeBackground(e);
  57. }
  58. if (nativeEvent)
  59. emitter.emit('element:unselect', { nativeEvent: true });
  60. return;
  61. };
  62. const singleSelect = (event, element, nativeEvent = true) => {
  63. // Clear states if clicked selected element.
  64. if (hasState(element, 'selected'))
  65. clear();
  66. else {
  67. const k = groupKey(element);
  68. const group = keyGroup.get(k);
  69. const groupSet = new Set(group);
  70. for (const e of elements) {
  71. if (groupSet.has(e))
  72. setState(e, 'selected');
  73. else {
  74. setState(e, 'unselected');
  75. removeLink(e);
  76. }
  77. if (e !== element)
  78. removeBackground(e);
  79. }
  80. appendLink(group);
  81. appendBackground(element);
  82. if (!nativeEvent)
  83. return;
  84. emitter.emit('element:select', Object.assign(Object.assign({}, event), { nativeEvent, data: {
  85. data: [datum(element), ...group.map(datum)],
  86. } }));
  87. }
  88. };
  89. const multipleSelect = (event, element, nativeEvent = true) => {
  90. const k = groupKey(element);
  91. const group = keyGroup.get(k);
  92. const groupSet = new Set(group);
  93. if (!hasState(element, 'selected')) {
  94. const hasSelectedGroup = group.some((e) => hasState(e, 'selected'));
  95. for (const e of elements) {
  96. if (groupSet.has(e))
  97. setState(e, 'selected');
  98. else if (!hasState(e, 'selected'))
  99. setState(e, 'unselected');
  100. }
  101. // Append link for each group only once.
  102. if (!hasSelectedGroup && link)
  103. appendLink(group);
  104. appendBackground(element);
  105. }
  106. else {
  107. // If there is no selected elements after resetting this group,
  108. // clear the states.
  109. const hasSelected = elements.some((e) => !groupSet.has(e) && hasState(e, 'selected'));
  110. if (!hasSelected)
  111. return clear();
  112. // If there are still some selected elements after resetting this group,
  113. // only remove the link.
  114. for (const e of group) {
  115. setState(e, 'unselected');
  116. removeLink(e);
  117. removeBackground(e);
  118. }
  119. }
  120. if (!nativeEvent)
  121. return;
  122. emitter.emit('element:select', Object.assign(Object.assign({}, event), { nativeEvent, data: {
  123. data: elements.filter((e) => hasState(e, 'selected')).map(datum),
  124. } }));
  125. };
  126. const click = (event) => {
  127. const { target: element, nativeEvent = true } = event;
  128. // Click non-element shape, reset.
  129. // Such as the rest of content area(background).
  130. if (!elementSet.has(element))
  131. return clear();
  132. if (single)
  133. return singleSelect(event, element, nativeEvent);
  134. return multipleSelect(event, element, nativeEvent);
  135. };
  136. root.addEventListener('click', click);
  137. const onSelect = (e) => {
  138. const { nativeEvent, data } = e;
  139. if (nativeEvent)
  140. return;
  141. const selectedData = single ? data.data.slice(0, 1) : data.data;
  142. for (const d of selectedData) {
  143. const element = (0, utils_1.selectElementByData)(elements, d, datum);
  144. click({ target: element, nativeEvent: false });
  145. }
  146. };
  147. const onUnSelect = () => {
  148. clear(false);
  149. };
  150. emitter.on('element:select', onSelect);
  151. emitter.on('element:unselect', onUnSelect);
  152. return () => {
  153. for (const e of elements)
  154. removeLink(e);
  155. root.removeEventListener('click', click);
  156. emitter.off('element:select', onSelect);
  157. emitter.off('element:unselect', onUnSelect);
  158. };
  159. }
  160. exports.elementSelect = elementSelect;
  161. function ElementSelect(_a) {
  162. var { createGroup, background = false, link = false } = _a, rest = __rest(_a, ["createGroup", "background", "link"]);
  163. return (context, _, emitter) => {
  164. const { container, view, options } = context;
  165. const { coordinate, scale } = view;
  166. const plotArea = (0, utils_1.selectPlotArea)(container);
  167. return elementSelect(plotArea, Object.assign({ elements: utils_1.selectG2Elements, datum: (0, utils_1.createDatumof)(view), groupKey: createGroup ? createGroup(view) : undefined, coordinate,
  168. scale, state: (0, utils_1.mergeState)(options, [
  169. ['selected', background ? {} : { lineWidth: '1', stroke: '#000' }],
  170. 'unselected',
  171. ]), background,
  172. link,
  173. emitter }, rest));
  174. };
  175. }
  176. exports.ElementSelect = ElementSelect;
  177. //# sourceMappingURL=elementSelect.js.map