index.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. "use strict";
  2. var __values = (this && this.__values) || function(o) {
  3. var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
  4. if (m) return m.call(o);
  5. if (o && typeof o.length === "number") return {
  6. next: function () {
  7. if (o && i >= o.length) o = void 0;
  8. return { value: o && o[i++], done: !o };
  9. }
  10. };
  11. throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
  12. };
  13. Object.defineProperty(exports, "__esModule", { value: true });
  14. exports.MiniMap = void 0;
  15. var lodash_es_1 = require("lodash-es");
  16. var MiniMap = /** @class */ (function () {
  17. function MiniMap(_a) {
  18. var _this = this;
  19. var lf = _a.lf, LogicFlow = _a.LogicFlow, options = _a.options;
  20. this.lf = null;
  21. this.container = null;
  22. this.miniMapWrap = null;
  23. this.miniMapContainer = null;
  24. this.lfMap = null;
  25. this.viewport = null;
  26. this.width = 150;
  27. this.height = 220;
  28. this.leftPosition = undefined;
  29. this.topPosition = undefined;
  30. this.rightPosition = undefined;
  31. this.bottomPosition = undefined;
  32. this.miniMapWidth = 450;
  33. this.miniMapHeight = 660;
  34. this.viewPortTop = 0;
  35. this.viewPortLeft = 0;
  36. this.startPosition = null;
  37. this.viewPortScale = 1;
  38. this.viewPortWidth = 150;
  39. this.viewPortHeight = 75;
  40. this.resetDataX = 0;
  41. this.resetDataY = 0;
  42. this.LogicFlow = null;
  43. this.isShow = false;
  44. this.isShowHeader = true;
  45. this.isShowCloseIcon = true;
  46. this.dragging = false;
  47. this.disabledPlugins = ['miniMap', 'control', 'selectionSelect'];
  48. /**
  49. * 显示mini map
  50. */
  51. this.show = function (leftPosition, topPosition) {
  52. _this.setView();
  53. if (!_this.isShow) {
  54. _this.createMiniMap(leftPosition, topPosition);
  55. }
  56. _this.isShow = true;
  57. };
  58. /**
  59. * 隐藏mini map
  60. */
  61. this.hide = function () {
  62. if (_this.isShow) {
  63. _this.removeMiniMap();
  64. }
  65. _this.isShow = false;
  66. };
  67. this.reset = function () {
  68. _this.lf.resetTranslate();
  69. _this.lf.resetZoom();
  70. _this.hide();
  71. _this.show();
  72. };
  73. this.startDrag = function (e) {
  74. document.addEventListener('mousemove', _this.drag);
  75. document.addEventListener('mouseup', _this.drop);
  76. _this.startPosition = {
  77. x: e.x,
  78. y: e.y,
  79. };
  80. };
  81. this.moveViewport = function (top, left) {
  82. var viewStyle = _this.viewport.style;
  83. _this.viewPortTop = top;
  84. _this.viewPortLeft = left;
  85. viewStyle.top = _this.viewPortTop + "px";
  86. viewStyle.left = _this.viewPortLeft + "px";
  87. };
  88. this.drag = function (e) {
  89. _this.dragging = true;
  90. var top = _this.viewPortTop + e.y - _this.startPosition.y;
  91. var left = _this.viewPortLeft + e.x - _this.startPosition.x;
  92. _this.moveViewport(top, left);
  93. _this.startPosition = {
  94. x: e.x,
  95. y: e.y,
  96. };
  97. var centerX = (_this.viewPortLeft + _this.viewPortWidth / 2)
  98. / _this.viewPortScale;
  99. var centerY = (_this.viewPortTop + _this.viewPortHeight / 2)
  100. / _this.viewPortScale;
  101. _this.lf.focusOn({
  102. coordinate: {
  103. x: centerX + _this.resetDataX,
  104. y: centerY + _this.resetDataY,
  105. },
  106. });
  107. };
  108. this.drop = function () {
  109. document.removeEventListener('mousemove', _this.drag);
  110. document.removeEventListener('mouseup', _this.drop);
  111. var top = _this.viewPortTop;
  112. var left = _this.viewPortLeft;
  113. if (_this.viewPortLeft > _this.width) {
  114. left = _this.width - _this.viewPortWidth;
  115. }
  116. if (_this.viewPortTop > _this.height) {
  117. top = _this.height - _this.viewPortHeight;
  118. }
  119. if (_this.viewPortLeft < -_this.width) {
  120. left = 0;
  121. }
  122. if (_this.viewPortTop < -_this.height) {
  123. top = 0;
  124. }
  125. _this.moveViewport(top, left);
  126. };
  127. this.mapClick = function (e) {
  128. if (_this.dragging) {
  129. _this.dragging = false;
  130. }
  131. else {
  132. var layerX = e.layerX, layerY = e.layerY;
  133. var ViewPortCenterX = layerX;
  134. var ViewPortCenterY = layerY;
  135. var graphData = _this.lf.getGraphRawData();
  136. var _a = _this.getBounds(graphData), left = _a.left, top_1 = _a.top;
  137. var resetGraphX = left + ViewPortCenterX / _this.viewPortScale;
  138. var resetGraphY = top_1 + ViewPortCenterY / _this.viewPortScale;
  139. _this.lf.focusOn({ coordinate: { x: resetGraphX, y: resetGraphY } });
  140. }
  141. };
  142. this.lf = lf;
  143. if (options && options.MiniMap) {
  144. this.setOption(options);
  145. }
  146. this.miniMapWidth = lf.graphModel.width;
  147. this.miniMapHeight = (lf.graphModel.width * this.height) / this.width;
  148. this.LogicFlow = LogicFlow;
  149. this.initMiniMap();
  150. }
  151. MiniMap.prototype.render = function (lf, container) {
  152. var _this = this;
  153. this.container = container;
  154. this.lf.on('history:change', function () {
  155. if (_this.isShow) {
  156. _this.setView();
  157. }
  158. });
  159. this.lf.on('graph:transform', lodash_es_1.throttle(function () {
  160. // 小地图已展示,并且没有拖拽小地图视口
  161. if (_this.isShow && !_this.dragging) {
  162. _this.setView();
  163. }
  164. }, 300));
  165. };
  166. MiniMap.prototype.init = function (option) {
  167. this.disabledPlugins = this.disabledPlugins.concat(option.disabledPlugins || []);
  168. };
  169. MiniMap.prototype.setOption = function (options) {
  170. var _a = options.MiniMap, _b = _a.width, width = _b === void 0 ? 150 : _b, _c = _a.height, height = _c === void 0 ? 220 : _c, _d = _a.isShowHeader, isShowHeader = _d === void 0 ? true : _d, _e = _a.isShowCloseIcon, isShowCloseIcon = _e === void 0 ? true : _e, _f = _a.leftPosition, leftPosition = _f === void 0 ? 0 : _f, _g = _a.topPosition, topPosition = _g === void 0 ? 0 : _g, rightPosition = _a.rightPosition, bottomPosition = _a.bottomPosition;
  171. this.width = width;
  172. this.height = height;
  173. this.isShowHeader = isShowHeader;
  174. this.isShowCloseIcon = isShowCloseIcon;
  175. this.viewPortWidth = width;
  176. this.leftPosition = leftPosition;
  177. this.topPosition = topPosition;
  178. this.rightPosition = rightPosition;
  179. this.bottomPosition = bottomPosition;
  180. };
  181. MiniMap.prototype.initMiniMap = function () {
  182. var miniMapWrap = document.createElement('div');
  183. miniMapWrap.className = 'lf-mini-map-graph';
  184. miniMapWrap.style.width = this.width + 4 + "px";
  185. miniMapWrap.style.height = this.height + "px";
  186. this.lfMap = new this.LogicFlow({
  187. width: this.lf.graphModel.width,
  188. height: (this.lf.graphModel.width * this.height) / this.width,
  189. container: miniMapWrap,
  190. isSilentMode: true,
  191. stopZoomGraph: true,
  192. stopScrollGraph: true,
  193. stopMoveGraph: true,
  194. hideAnchors: true,
  195. hoverOutline: false,
  196. disabledPlugins: this.disabledPlugins,
  197. });
  198. // minimap中禁用adapter。
  199. this.lfMap.adapterIn = function (a) { return a; };
  200. this.lfMap.adapterOut = function (a) { return a; };
  201. this.miniMapWrap = miniMapWrap;
  202. this.createViewPort();
  203. miniMapWrap.addEventListener('click', this.mapClick);
  204. };
  205. MiniMap.prototype.createMiniMap = function (left, top) {
  206. var miniMapContainer = document.createElement('div');
  207. miniMapContainer.appendChild(this.miniMapWrap);
  208. if (typeof left !== 'undefined' || typeof top !== 'undefined') {
  209. miniMapContainer.style.left = (left || 0) + "px";
  210. miniMapContainer.style.top = (top || 0) + "px";
  211. }
  212. else {
  213. if (typeof this.rightPosition !== 'undefined') {
  214. miniMapContainer.style.right = this.rightPosition + "px";
  215. }
  216. else if (typeof this.leftPosition !== 'undefined') {
  217. miniMapContainer.style.left = this.leftPosition + "px";
  218. }
  219. if (typeof this.bottomPosition !== 'undefined') {
  220. miniMapContainer.style.bottom = this.bottomPosition + "px";
  221. }
  222. else if (typeof this.topPosition !== 'undefined') {
  223. miniMapContainer.style.top = this.topPosition + "px";
  224. }
  225. }
  226. miniMapContainer.style.position = 'absolute';
  227. miniMapContainer.className = 'lf-mini-map';
  228. if (!this.isShowCloseIcon) {
  229. miniMapContainer.classList.add('lf-mini-map-no-close-icon');
  230. }
  231. if (!this.isShowHeader) {
  232. miniMapContainer.classList.add('lf-mini-map-no-header');
  233. }
  234. this.container.appendChild(miniMapContainer);
  235. this.miniMapWrap.appendChild(this.viewport);
  236. var header = document.createElement('div');
  237. header.className = 'lf-mini-map-header';
  238. header.innerText = MiniMap.headerTitle;
  239. miniMapContainer.appendChild(header);
  240. var close = document.createElement('span');
  241. close.className = 'lf-mini-map-close';
  242. close.addEventListener('click', this.hide);
  243. miniMapContainer.appendChild(close);
  244. this.miniMapContainer = miniMapContainer;
  245. };
  246. MiniMap.prototype.removeMiniMap = function () {
  247. this.container.removeChild(this.miniMapContainer);
  248. };
  249. /**
  250. * 计算所有图形一起,占领的区域范围。
  251. * @param data
  252. */
  253. MiniMap.prototype.getBounds = function (data) {
  254. var left = 0;
  255. var right = this.miniMapWidth;
  256. var top = 0;
  257. var bottom = this.miniMapHeight;
  258. var nodes = data.nodes;
  259. if (nodes && nodes.length > 0) {
  260. // 因为获取的节点不知道真实的宽高,这里需要补充一点数值
  261. nodes.forEach(function (_a) {
  262. var x = _a.x, y = _a.y, _b = _a.width, width = _b === void 0 ? 200 : _b, _c = _a.height, height = _c === void 0 ? 200 : _c;
  263. var nodeLeft = x - width / 2;
  264. var nodeRight = x + width / 2;
  265. var nodeTop = y - height / 2;
  266. var nodeBottom = y + height / 2;
  267. left = nodeLeft < left ? nodeLeft : left;
  268. right = nodeRight > right ? nodeRight : right;
  269. top = nodeTop < top ? nodeTop : top;
  270. bottom = nodeBottom > bottom ? nodeBottom : bottom;
  271. });
  272. }
  273. return {
  274. left: left,
  275. top: top,
  276. bottom: bottom,
  277. right: right,
  278. };
  279. };
  280. /**
  281. * 将负值的平移转换为正值。
  282. * 保证渲染的时候,minimap能完全展示。
  283. * 获取将画布所有元素平移到0,0开始时,所有节点数据
  284. */
  285. MiniMap.prototype.resetData = function (data) {
  286. var nodes = data.nodes, edges = data.edges;
  287. var left = 0;
  288. var top = 0;
  289. if (nodes && nodes.length > 0) {
  290. // 因为获取的节点不知道真实的宽高,这里需要补充一点数值
  291. nodes.forEach(function (_a) {
  292. var x = _a.x, y = _a.y, _b = _a.width, width = _b === void 0 ? 200 : _b, _c = _a.height, height = _c === void 0 ? 200 : _c;
  293. var nodeLeft = x - width / 2;
  294. var nodeTop = y - height / 2;
  295. left = nodeLeft < left ? nodeLeft : left;
  296. top = nodeTop < top ? nodeTop : top;
  297. });
  298. if (left < 0 || top < 0) {
  299. this.resetDataX = left;
  300. this.resetDataY = top;
  301. nodes.forEach(function (node) {
  302. node.x = node.x - left;
  303. node.y = node.y - top;
  304. if (node.text) {
  305. node.text.x = node.text.x - left;
  306. node.text.y = node.text.y - top;
  307. }
  308. });
  309. edges.forEach(function (edge) {
  310. if (edge.startPoint) {
  311. edge.startPoint.x = edge.startPoint.x - left;
  312. edge.startPoint.y = edge.startPoint.y - top;
  313. }
  314. if (edge.endPoint) {
  315. edge.endPoint.x = edge.endPoint.x - left;
  316. edge.endPoint.y = edge.endPoint.y - top;
  317. }
  318. if (edge.text) {
  319. edge.text.x = edge.text.x - left;
  320. edge.text.y = edge.text.y - top;
  321. }
  322. if (edge.pointsList) {
  323. edge.pointsList.forEach(function (point) {
  324. point.x = point.x - left;
  325. point.y = point.y - top;
  326. });
  327. }
  328. });
  329. }
  330. }
  331. return data;
  332. };
  333. /**
  334. * 显示导航
  335. * 显示视口范围
  336. * 1. 基于画布的范围比例,设置视口范围比例。宽度默认为导航宽度。
  337. */
  338. MiniMap.prototype.setView = function () {
  339. var e_1, _a;
  340. // 1. 获取到图中所有的节点中的位置,将其偏移到原点开始(避免节点位置为负的时候无法展示问题)。
  341. var graphData = this.lf.getGraphRawData();
  342. var data = this.resetData(graphData);
  343. // 由于随时都会有新节点注册进来,需要同步将注册的
  344. var viewMap = this.lf.viewMap;
  345. var modelMap = this.lf.graphModel.modelMap;
  346. var minimapViewMap = this.lfMap.viewMap;
  347. try {
  348. // todo: no-restricted-syntax
  349. for (var _b = __values(viewMap.keys()), _c = _b.next(); !_c.done; _c = _b.next()) {
  350. var key = _c.value;
  351. if (!minimapViewMap.has(key)) {
  352. this.lfMap.setView(key, viewMap.get(key));
  353. this.lfMap.graphModel.modelMap.set(key, modelMap.get(key));
  354. }
  355. }
  356. }
  357. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  358. finally {
  359. try {
  360. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  361. }
  362. finally { if (e_1) throw e_1.error; }
  363. }
  364. this.lfMap.render(data);
  365. // 2. 将偏移后的数据渲染到minimap画布上
  366. // 3. 计算出所有节点在一起的边界。
  367. var _d = this.getBounds(data), left = _d.left, top = _d.top, right = _d.right, bottom = _d.bottom;
  368. // 4. 计算所有节点的边界与minimap看板的边界的比例.
  369. var realWidthScale = this.width / (right - left);
  370. var realHeightScale = this.height / (bottom - top);
  371. // 5. 取比例最小的值,将渲染的画布缩小对应比例。
  372. var innerStyle = this.miniMapWrap.firstChild.style;
  373. var scale = Math.min(realWidthScale, realHeightScale);
  374. innerStyle.transform = "matrix(" + scale + ", 0, 0, " + scale + ", 0, 0)";
  375. innerStyle.transformOrigin = 'left top';
  376. innerStyle.height = bottom - Math.min(top, 0) + "px";
  377. innerStyle.width = right - Math.min(left, 0) + "px";
  378. this.viewPortScale = scale;
  379. this.setViewPort(scale, {
  380. left: left,
  381. top: top,
  382. right: right,
  383. bottom: bottom,
  384. });
  385. };
  386. // 设置视口
  387. MiniMap.prototype.setViewPort = function (scale, _a) {
  388. var left = _a.left, right = _a.right, top = _a.top, bottom = _a.bottom;
  389. var viewStyle = this.viewport.style;
  390. viewStyle.width = this.viewPortWidth + "px";
  391. viewStyle.height = (this.viewPortWidth) / (this.lf.graphModel.width / this.lf.graphModel.height) + "px";
  392. var _b = this.lf.getTransform(), TRANSLATE_X = _b.TRANSLATE_X, TRANSLATE_Y = _b.TRANSLATE_Y, SCALE_X = _b.SCALE_X, SCALE_Y = _b.SCALE_Y;
  393. var realWidth = right - left;
  394. // 视口宽 = 小地图宽 / (所有元素一起占据的真实宽 / 绘布宽)
  395. var viewPortWidth = (this.width) / (realWidth / this.lf.graphModel.width);
  396. // 实际视口宽 = 小地图宽 * 占宽度比例
  397. var realViewPortWidth = this.width * (viewPortWidth / this.width);
  398. var graphRatio = (this.lf.graphModel.width / this.lf.graphModel.height);
  399. // 视口实际高 = 视口实际宽 / (绘布宽 / 绘布高)
  400. var realViewPortHeight = realViewPortWidth / graphRatio;
  401. var graphData = this.lf.getGraphRawData();
  402. var _c = this.getBounds(graphData), graphLeft = _c.left, graphTop = _c.top;
  403. var viewportLeft = graphLeft;
  404. var viewportTop = graphTop;
  405. viewportLeft += TRANSLATE_X / SCALE_X;
  406. viewportTop += TRANSLATE_Y / SCALE_Y;
  407. this.viewPortTop = viewportTop > 0 ? 0 : (-viewportTop * scale);
  408. this.viewPortLeft = viewportLeft > 0 ? 0 : (-viewportLeft * scale);
  409. this.viewPortWidth = realViewPortWidth;
  410. this.viewPortHeight = realViewPortHeight;
  411. viewStyle.top = this.viewPortTop + "px";
  412. viewStyle.left = this.viewPortLeft + "px";
  413. viewStyle.width = realViewPortWidth / SCALE_X + "px";
  414. viewStyle.height = realViewPortHeight / SCALE_Y + "px";
  415. };
  416. // 预览视窗
  417. MiniMap.prototype.createViewPort = function () {
  418. var div = document.createElement('div');
  419. div.className = 'lf-minimap-viewport';
  420. div.addEventListener('mousedown', this.startDrag);
  421. this.viewport = div;
  422. };
  423. MiniMap.pluginName = 'miniMap';
  424. MiniMap.width = 150;
  425. MiniMap.height = 220;
  426. MiniMap.viewPortWidth = 150;
  427. MiniMap.viewPortHeight = 75;
  428. MiniMap.isShowHeader = true;
  429. MiniMap.isShowCloseIcon = true;
  430. MiniMap.leftPosition = 0;
  431. MiniMap.topPosition = 0;
  432. MiniMap.rightPosition = null;
  433. MiniMap.bottomPosition = null;
  434. MiniMap.headerTitle = '导航';
  435. return MiniMap;
  436. }());
  437. exports.MiniMap = MiniMap;
  438. exports.default = MiniMap;