group-component.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var tslib_1 = require("tslib");
  4. var util_1 = require("@antv/util");
  5. var event_1 = require("../util/event");
  6. var matrix_1 = require("../util/matrix");
  7. var util_2 = require("../util/util");
  8. var component_1 = require("./component");
  9. var STATUS_UPDATE = 'update_status';
  10. var COPY_PROPERTIES = ['visible', 'tip', 'delegateObject']; // 更新对象时需要复制的属性
  11. var COPY_PROPERTIES_EXCLUDES = ['container', 'group', 'shapesMap', 'isRegister', 'isUpdating', 'destroyed']; // 更新子组件时排除的属性
  12. var GroupComponent = /** @class */ (function (_super) {
  13. tslib_1.__extends(GroupComponent, _super);
  14. function GroupComponent() {
  15. return _super !== null && _super.apply(this, arguments) || this;
  16. }
  17. GroupComponent.prototype.getDefaultCfg = function () {
  18. var cfg = _super.prototype.getDefaultCfg.call(this);
  19. return tslib_1.__assign(tslib_1.__assign({}, cfg), { container: null,
  20. /**
  21. * @private
  22. * 缓存图形的 Map
  23. */
  24. shapesMap: {}, group: null, capture: true,
  25. /**
  26. * @private 组件或者图形是否允许注册
  27. * @type {false}
  28. */
  29. isRegister: false,
  30. /**
  31. * @private 是否正在更新
  32. * @type {false}
  33. */
  34. isUpdating: false,
  35. /**
  36. * @private
  37. * 是否初始状态,一旦 render,update 后,这个状态就变成 false, clear 后恢复
  38. */
  39. isInit: true });
  40. };
  41. GroupComponent.prototype.remove = function () {
  42. this.clear();
  43. var group = this.get('group');
  44. group.remove();
  45. };
  46. GroupComponent.prototype.clear = function () {
  47. var group = this.get('group');
  48. group.clear();
  49. this.set('shapesMap', {});
  50. this.clearOffScreenCache();
  51. this.set('isInit', true);
  52. };
  53. GroupComponent.prototype.getChildComponentById = function (id) {
  54. var group = this.getElementById(id);
  55. var inst = group && group.get('component');
  56. return inst;
  57. };
  58. GroupComponent.prototype.getElementById = function (id) {
  59. return this.get('shapesMap')[id];
  60. };
  61. GroupComponent.prototype.getElementByLocalId = function (localId) {
  62. var id = this.getElementId(localId);
  63. return this.getElementById(id);
  64. };
  65. GroupComponent.prototype.getElementsByName = function (name) {
  66. var rst = [];
  67. util_1.each(this.get('shapesMap'), function (elem) {
  68. if (elem.get('name') === name) {
  69. rst.push(elem);
  70. }
  71. });
  72. return rst;
  73. };
  74. GroupComponent.prototype.getContainer = function () {
  75. return this.get('container');
  76. };
  77. GroupComponent.prototype.updateInner = function (cfg) {
  78. // this.updateInner();
  79. // this.set('isUpdating', false);
  80. this.offScreenRender();
  81. if (this.get('updateAutoRender')) {
  82. this.render();
  83. }
  84. };
  85. GroupComponent.prototype.render = function () {
  86. var offScreenGroup = this.get('offScreenGroup');
  87. if (!offScreenGroup) {
  88. offScreenGroup = this.offScreenRender();
  89. }
  90. var group = this.get('group');
  91. this.updateElements(offScreenGroup, group);
  92. this.deleteElements();
  93. this.applyOffset();
  94. if (!this.get('eventInitted')) {
  95. this.initEvent();
  96. this.set('eventInitted', true);
  97. }
  98. this.set('isInit', false);
  99. };
  100. GroupComponent.prototype.show = function () {
  101. var group = this.get('group');
  102. group.show();
  103. this.set('visible', true);
  104. };
  105. GroupComponent.prototype.hide = function () {
  106. var group = this.get('group');
  107. group.hide();
  108. this.set('visible', false);
  109. };
  110. GroupComponent.prototype.setCapture = function (capture) {
  111. var group = this.get('group');
  112. group.set('capture', capture);
  113. this.set('capture', capture);
  114. };
  115. GroupComponent.prototype.destroy = function () {
  116. this.removeEvent();
  117. this.remove();
  118. _super.prototype.destroy.call(this);
  119. };
  120. GroupComponent.prototype.getBBox = function () {
  121. return this.get('group').getCanvasBBox();
  122. };
  123. GroupComponent.prototype.getLayoutBBox = function () {
  124. var group = this.get('group');
  125. // 防止被 clear 了,offScreenBBox 不存在
  126. var bbox = this.getInnerLayoutBBox();
  127. var matrix = group.getTotalMatrix();
  128. if (matrix) {
  129. bbox = matrix_1.applyMatrix2BBox(matrix, bbox);
  130. }
  131. return bbox; // 默认返回 getBBox,不同的组件内部单独实现
  132. };
  133. // 复写 on, off, emit 透传到 group
  134. GroupComponent.prototype.on = function (evt, callback, once) {
  135. var group = this.get('group');
  136. group.on(evt, callback, once);
  137. return this;
  138. };
  139. GroupComponent.prototype.off = function (evt, callback) {
  140. var group = this.get('group');
  141. group && group.off(evt, callback);
  142. return this;
  143. };
  144. GroupComponent.prototype.emit = function (eventName, eventObject) {
  145. var group = this.get('group');
  146. group.emit(eventName, eventObject);
  147. };
  148. GroupComponent.prototype.init = function () {
  149. _super.prototype.init.call(this);
  150. if (!this.get('group')) {
  151. this.initGroup();
  152. }
  153. this.offScreenRender(); // 绘制离屏 group
  154. };
  155. // 获取组件内部布局占的包围盒
  156. GroupComponent.prototype.getInnerLayoutBBox = function () {
  157. return this.get('offScreenBBox') || this.get('group').getBBox();
  158. };
  159. // 抛出委托对象
  160. GroupComponent.prototype.delegateEmit = function (eventName, eventObject) {
  161. var group = this.get('group');
  162. eventObject.target = group;
  163. group.emit(eventName, eventObject);
  164. event_1.propagationDelegate(group, eventName, eventObject);
  165. };
  166. // 创建离屏的 group ,不添加在 canvas 中
  167. GroupComponent.prototype.createOffScreenGroup = function () {
  168. var group = this.get('group');
  169. var GroupClass = group.getGroupBase(); // 获取分组的构造函数
  170. var newGroup = new GroupClass({
  171. delegateObject: this.getDelegateObject(),
  172. });
  173. return newGroup;
  174. };
  175. // 应用 offset
  176. GroupComponent.prototype.applyOffset = function () {
  177. var offsetX = this.get('offsetX');
  178. var offsetY = this.get('offsetY');
  179. this.moveElementTo(this.get('group'), {
  180. x: offsetX,
  181. y: offsetY,
  182. });
  183. };
  184. GroupComponent.prototype.initGroup = function () {
  185. var container = this.get('container');
  186. this.set('group', container.addGroup({
  187. id: this.get('id'),
  188. name: this.get('name'),
  189. capture: this.get('capture'),
  190. visible: this.get('visible'),
  191. isComponent: true,
  192. component: this,
  193. delegateObject: this.getDelegateObject(),
  194. }));
  195. };
  196. // 离屏渲染
  197. GroupComponent.prototype.offScreenRender = function () {
  198. this.clearOffScreenCache();
  199. var offScreenGroup = this.createOffScreenGroup();
  200. this.renderInner(offScreenGroup);
  201. this.set('offScreenGroup', offScreenGroup);
  202. // 包含包围盒的 bbox
  203. this.set('offScreenBBox', util_2.getBBoxWithClip(offScreenGroup));
  204. return offScreenGroup;
  205. };
  206. /**
  207. * @protected
  208. * 在组件上添加分组,主要解决 isReigeter 的问题
  209. * @param {IGroup} parent 父元素
  210. * @param {object} cfg 分组的配置项
  211. */
  212. GroupComponent.prototype.addGroup = function (parent, cfg) {
  213. this.appendDelegateObject(parent, cfg);
  214. var group = parent.addGroup(cfg);
  215. if (this.get('isRegister')) {
  216. this.registerElement(group);
  217. }
  218. return group;
  219. };
  220. /**
  221. * @protected
  222. * 在组件上添加图形,主要解决 isReigeter 的问题
  223. * @param {IGroup} parent 父元素
  224. * @param {object} cfg 分组的配置项
  225. */
  226. GroupComponent.prototype.addShape = function (parent, cfg) {
  227. this.appendDelegateObject(parent, cfg);
  228. var shape = parent.addShape(cfg);
  229. if (this.get('isRegister')) {
  230. this.registerElement(shape);
  231. }
  232. return shape;
  233. };
  234. /**
  235. * 在组件上添加子组件
  236. *
  237. * @param parent 父元素
  238. * @param cfg 子组件配置项
  239. */
  240. GroupComponent.prototype.addComponent = function (parent, cfg) {
  241. var id = cfg.id, Ctor = cfg.component, restCfg = tslib_1.__rest(cfg, ["id", "component"]);
  242. // @ts-ignore
  243. var inst = new Ctor(tslib_1.__assign(tslib_1.__assign({}, restCfg), { id: id, container: parent, updateAutoRender: this.get('updateAutoRender') }));
  244. inst.init();
  245. inst.render();
  246. if (this.get('isRegister')) {
  247. this.registerElement(inst.get('group'));
  248. }
  249. return inst;
  250. };
  251. GroupComponent.prototype.initEvent = function () { };
  252. GroupComponent.prototype.removeEvent = function () {
  253. var group = this.get('group');
  254. group.off();
  255. };
  256. GroupComponent.prototype.getElementId = function (localId) {
  257. var id = this.get('id'); // 组件的 Id
  258. var name = this.get('name'); // 组件的名称
  259. return id + "-" + name + "-" + localId;
  260. };
  261. GroupComponent.prototype.registerElement = function (element) {
  262. var id = element.get('id');
  263. this.get('shapesMap')[id] = element;
  264. };
  265. GroupComponent.prototype.unregisterElement = function (element) {
  266. var id = element.get('id');
  267. delete this.get('shapesMap')[id];
  268. };
  269. // 移动元素
  270. GroupComponent.prototype.moveElementTo = function (element, point) {
  271. var matrix = matrix_1.getMatrixByTranslate(point);
  272. element.attr('matrix', matrix);
  273. };
  274. /**
  275. * 图形元素新出现时的动画,默认图形从透明度 0 到当前透明度
  276. * @protected
  277. * @param {string} elmentName 图形元素名称
  278. * @param {IElement} newElement 新的图形元素
  279. * @param {object} animateCfg 动画的配置项
  280. */
  281. GroupComponent.prototype.addAnimation = function (elmentName, newElement, animateCfg) {
  282. // 缓存透明度
  283. var originOpacity = newElement.attr('opacity');
  284. if (util_1.isNil(originOpacity)) {
  285. originOpacity = 1;
  286. }
  287. newElement.attr('opacity', 0);
  288. newElement.animate({ opacity: originOpacity }, animateCfg);
  289. };
  290. /**
  291. * 图形元素新出现时的动画,默认图形从透明度 0 到当前透明度
  292. * @protected
  293. * @param {string} elmentName 图形元素名称
  294. * @param {IElement} originElement 要删除的图形元素
  295. * @param {object} animateCfg 动画的配置项
  296. */
  297. GroupComponent.prototype.removeAnimation = function (elementName, originElement, animateCfg) {
  298. originElement.animate({ opacity: 0 }, animateCfg);
  299. };
  300. /**
  301. * 图形元素的更新动画
  302. * @param {string} elmentName 图形元素名称
  303. * @param {IElement} originElement 现有的图形元素
  304. * @param {object} newAttrs 新的图形元素
  305. * @param {object} animateCfg 动画的配置项
  306. */
  307. GroupComponent.prototype.updateAnimation = function (elementName, originElement, newAttrs, animateCfg) {
  308. originElement.animate(newAttrs, animateCfg);
  309. };
  310. // 更新组件的图形
  311. GroupComponent.prototype.updateElements = function (newGroup, originGroup) {
  312. var _this = this;
  313. var animate = this.get('animate');
  314. var animateOption = this.get('animateOption');
  315. var children = newGroup.getChildren().slice(0); // 创建一个新数组,防止添加到 originGroup 时, children 变动
  316. var preElement; // 前面已经匹配到的图形元素,用于
  317. util_1.each(children, function (element) {
  318. var elementId = element.get('id');
  319. var originElement = _this.getElementById(elementId);
  320. var elementName = element.get('name');
  321. if (originElement) {
  322. if (element.get('isComponent')) {
  323. // 嵌套子组件更新
  324. var childComponent = element.get('component');
  325. var origChildComponent = originElement.get('component');
  326. var newCfg = util_1.pick(childComponent.cfg, util_1.difference(util_1.keys(childComponent.cfg), COPY_PROPERTIES_EXCLUDES));
  327. origChildComponent.update(newCfg);
  328. originElement.set(STATUS_UPDATE, 'update');
  329. }
  330. else {
  331. var replaceAttrs = _this.getReplaceAttrs(originElement, element);
  332. // 更新
  333. if (animate && animateOption.update) {
  334. // 没有动画
  335. _this.updateAnimation(elementName, originElement, replaceAttrs, animateOption.update);
  336. }
  337. else {
  338. // originElement.attrs = replaceAttrs; // 直接替换
  339. originElement.attr(replaceAttrs);
  340. }
  341. // 如果是分组,则继续执行
  342. if (element.isGroup()) {
  343. _this.updateElements(element, originElement);
  344. }
  345. // 复制属性
  346. util_1.each(COPY_PROPERTIES, function (name) {
  347. originElement.set(name, element.get(name));
  348. });
  349. util_2.updateClip(originElement, element);
  350. preElement = originElement;
  351. // 执行完更新后设置状态位为更新
  352. originElement.set(STATUS_UPDATE, 'update');
  353. }
  354. }
  355. else {
  356. // 没有对应的图形,则插入当前图形
  357. originGroup.add(element); // 应该在 group 加个 insertAt 的方法
  358. var siblings = originGroup.getChildren(); // 兄弟节点
  359. siblings.splice(siblings.length - 1, 1); // 先从数组中移除,然后放到合适的位置
  360. if (preElement) {
  361. // 前面已经有更新的图形或者插入的图形,则在这个图形后面插入
  362. var index = siblings.indexOf(preElement);
  363. siblings.splice(index + 1, 0, element); // 在已经更新的图形元素后面插入
  364. }
  365. else {
  366. siblings.unshift(element);
  367. }
  368. _this.registerElement(element); // 注册节点
  369. element.set(STATUS_UPDATE, 'add'); // 执行完更新后设置状态位为添加
  370. if (element.get('isComponent')) {
  371. // 直接新增子组件container属性,实例不变
  372. var childComponent = element.get('component');
  373. childComponent.set('container', originGroup);
  374. }
  375. else if (element.isGroup()) {
  376. // 如果元素是新增加的元素,则遍历注册所有的子节点
  377. _this.registerNewGroup(element);
  378. }
  379. preElement = element;
  380. if (animate) {
  381. var animateCfg = _this.get('isInit') ? animateOption.appear : animateOption.enter;
  382. if (animateCfg) {
  383. _this.addAnimation(elementName, element, animateCfg);
  384. }
  385. }
  386. }
  387. });
  388. };
  389. GroupComponent.prototype.clearUpdateStatus = function (group) {
  390. var children = group.getChildren();
  391. util_1.each(children, function (el) {
  392. el.set(STATUS_UPDATE, null); // 清理掉更新状态
  393. });
  394. };
  395. // 清理离屏缓存
  396. GroupComponent.prototype.clearOffScreenCache = function () {
  397. var offScreenGroup = this.get('offScreenGroup');
  398. if (offScreenGroup) {
  399. // 销毁原先的离线 Group
  400. offScreenGroup.destroy();
  401. }
  402. this.set('offScreenGroup', null);
  403. this.set('offScreenBBox', null);
  404. };
  405. // private updateInner() {
  406. // const group = this.get('group');
  407. // const newGroup = this.createOffScreenGroup();
  408. // this.renderInner(newGroup);
  409. // this.applyOffset();
  410. // this.updateElements(newGroup, group);
  411. // this.deleteElements();
  412. // newGroup.destroy(); // 销毁虚拟分组
  413. // }
  414. // 获取发生委托时的对象,在事件中抛出
  415. GroupComponent.prototype.getDelegateObject = function () {
  416. var _a;
  417. var name = this.get('name');
  418. var delegateObject = (_a = {},
  419. _a[name] = this,
  420. _a.component = this,
  421. _a);
  422. return delegateObject;
  423. };
  424. // 附加委托信息,用于事件
  425. GroupComponent.prototype.appendDelegateObject = function (parent, cfg) {
  426. var parentObject = parent.get('delegateObject');
  427. if (!cfg.delegateObject) {
  428. cfg.delegateObject = {};
  429. }
  430. util_1.mix(cfg.delegateObject, parentObject); // 将父元素上的委托信息复制到自身
  431. };
  432. // 获取需要替换的属性,如果原先图形元素存在,而新图形不存在,则设置 undefined
  433. GroupComponent.prototype.getReplaceAttrs = function (originElement, newElement) {
  434. var originAttrs = originElement.attr();
  435. var newAttrs = newElement.attr();
  436. util_1.each(originAttrs, function (v, k) {
  437. if (newAttrs[k] === undefined) {
  438. newAttrs[k] = undefined;
  439. }
  440. });
  441. return newAttrs;
  442. };
  443. GroupComponent.prototype.registerNewGroup = function (group) {
  444. var _this = this;
  445. var children = group.getChildren();
  446. util_1.each(children, function (element) {
  447. _this.registerElement(element); // 注册节点
  448. element.set(STATUS_UPDATE, 'add'); // 执行完更新后设置状态位为添加
  449. if (element.isGroup()) {
  450. _this.registerNewGroup(element);
  451. }
  452. });
  453. };
  454. // 移除多余的元素
  455. GroupComponent.prototype.deleteElements = function () {
  456. var _this = this;
  457. var shapesMap = this.get('shapesMap');
  458. var deleteArray = [];
  459. // 遍历获取需要删除的图形元素
  460. util_1.each(shapesMap, function (element, id) {
  461. if (!element.get(STATUS_UPDATE) || element.destroyed) {
  462. deleteArray.push([id, element]);
  463. }
  464. else {
  465. element.set(STATUS_UPDATE, null); // 清理掉更新状态
  466. }
  467. });
  468. var animate = this.get('animate');
  469. var animateOption = this.get('animateOption');
  470. // 删除图形元素
  471. util_1.each(deleteArray, function (item) {
  472. var id = item[0], element = item[1];
  473. if (!element.destroyed) {
  474. var elementName = element.get('name');
  475. if (animate && animateOption.leave) {
  476. // 需要动画结束时移除图形
  477. var callbackAnimCfg = util_1.mix({
  478. callback: function () {
  479. _this.removeElement(element);
  480. },
  481. }, animateOption.leave);
  482. _this.removeAnimation(elementName, element, callbackAnimCfg);
  483. }
  484. else {
  485. _this.removeElement(element);
  486. }
  487. }
  488. delete shapesMap[id]; // 从缓存中移除
  489. });
  490. };
  491. GroupComponent.prototype.removeElement = function (element) {
  492. if (element.get('isGroup')) {
  493. var component = element.get('component');
  494. if (component) {
  495. component.destroy();
  496. }
  497. }
  498. element.remove();
  499. };
  500. return GroupComponent;
  501. }(component_1.default));
  502. exports.default = GroupComponent;
  503. //# sourceMappingURL=group-component.js.map