index.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /**
  2. * 快照插件,生成视图
  3. */
  4. var Snapshot = /** @class */ (function () {
  5. function Snapshot(_a) {
  6. var _this = this;
  7. var lf = _a.lf;
  8. this.lf = lf;
  9. this.customCssRules = '';
  10. this.useGlobalRules = true;
  11. /* 下载快照 */
  12. lf.getSnapshot = function (fileName, backgroundColor) {
  13. _this.getSnapshot(fileName, backgroundColor);
  14. };
  15. /* 获取Blob对象,用户图片上传 */
  16. lf.getSnapshotBlob = function (backgroundColor) { return _this.getSnapshotBlob(backgroundColor); };
  17. /* 获取Base64对象,用户图片上传 */
  18. lf.getSnapshotBase64 = function (backgroundColor) { return _this.getSnapshotBase64(backgroundColor); };
  19. }
  20. /* 获取svgRoot对象 */
  21. Snapshot.prototype.getSvgRootElement = function (lf) {
  22. var _this = this;
  23. this.offsetX = Number.MAX_SAFE_INTEGER;
  24. this.offsetY = Number.MAX_SAFE_INTEGER;
  25. lf.graphModel.nodes.forEach(function (item) {
  26. var x = item.x, width = item.width, y = item.y, height = item.height;
  27. var offsetX = x - width / 2;
  28. var offsetY = y - height / 2;
  29. if (offsetX < _this.offsetX) {
  30. _this.offsetX = offsetX - 5;
  31. }
  32. if (offsetY < _this.offsetY) {
  33. _this.offsetY = offsetY - 5;
  34. }
  35. });
  36. lf.graphModel.edges.forEach(function (edge) {
  37. if (edge.pointsList) {
  38. edge.pointsList.forEach(function (point) {
  39. var x = point.x, y = point.y;
  40. if (x < _this.offsetX) {
  41. _this.offsetX = x - 5;
  42. }
  43. if (y < _this.offsetY) {
  44. _this.offsetY = y - 5;
  45. }
  46. });
  47. }
  48. });
  49. var svgRootElement = lf.container.querySelector('.lf-canvas-overlay');
  50. return svgRootElement;
  51. };
  52. Snapshot.prototype.triggerDownload = function (imgURI) {
  53. var evt = new MouseEvent('click', {
  54. view: window,
  55. bubbles: false,
  56. cancelable: true,
  57. });
  58. var a = document.createElement('a');
  59. a.setAttribute('download', this.fileName);
  60. a.setAttribute('href', imgURI);
  61. a.setAttribute('target', '_blank');
  62. a.dispatchEvent(evt);
  63. };
  64. Snapshot.prototype.removeAnchor = function (element) {
  65. var childNodes = element.childNodes;
  66. var childLength = element.childNodes && element.childNodes.length;
  67. for (var i = 0; i < childLength; i++) {
  68. var child = childNodes[i];
  69. var classList = (child.classList && Array.from(child.classList)) || [];
  70. if (classList.indexOf('lf-anchor') > -1) {
  71. element.removeChild(element.childNodes[i]);
  72. childLength--;
  73. i--;
  74. }
  75. }
  76. };
  77. /* 下载图片 */
  78. Snapshot.prototype.getSnapshot = function (fileName, backgroundColor) {
  79. var _this = this;
  80. this.fileName = fileName || "logic-flow." + Date.now() + ".png";
  81. var svg = this.getSvgRootElement(this.lf);
  82. this.getCanvasData(svg, backgroundColor).then(function (canvas) {
  83. var imgURI = canvas.toDataURL('image/png')
  84. .replace('image/png', 'image/octet-stream');
  85. _this.triggerDownload(imgURI);
  86. });
  87. };
  88. /* 获取base64对象 */
  89. Snapshot.prototype.getSnapshotBase64 = function (backgroundColor) {
  90. var _this = this;
  91. var svg = this.getSvgRootElement(this.lf);
  92. return new Promise(function (resolve) {
  93. _this.getCanvasData(svg, backgroundColor).then(function (canvas) {
  94. var base64 = canvas.toDataURL('image/png');
  95. // 输出图片数据以及图片宽高
  96. resolve({ data: base64, width: canvas.width, height: canvas.height });
  97. });
  98. });
  99. };
  100. /* 获取Blob对象 */
  101. Snapshot.prototype.getSnapshotBlob = function (backgroundColor) {
  102. var _this = this;
  103. var svg = this.getSvgRootElement(this.lf);
  104. return new Promise(function (resolve) {
  105. _this.getCanvasData(svg, backgroundColor).then(function (canvas) {
  106. canvas.toBlob(function (blob) {
  107. // 输出图片数据以及图片宽高
  108. resolve({ data: blob, width: canvas.width, height: canvas.height });
  109. }, 'image/png');
  110. });
  111. });
  112. };
  113. Snapshot.prototype.getClassRules = function () {
  114. var rules = '';
  115. if (this.useGlobalRules) {
  116. var styleSheets = document.styleSheets;
  117. for (var i = 0; i < styleSheets.length; i++) {
  118. var sheet = styleSheets[i];
  119. for (var j = 0; j < sheet.cssRules.length; j++) {
  120. rules += sheet.cssRules[j].cssText;
  121. }
  122. }
  123. }
  124. if (this.customCssRules) {
  125. rules += this.customCssRules;
  126. }
  127. return rules;
  128. };
  129. // 获取图片生成中中间产物canvas对象,用户转换为其他需要的格式
  130. Snapshot.prototype.getCanvasData = function (svg, backgroundColor) {
  131. var _this = this;
  132. var copy = svg.cloneNode(true);
  133. var graph = copy.lastChild;
  134. var childLength = graph.childNodes && graph.childNodes.length;
  135. if (childLength) {
  136. for (var i = 0; i < childLength; i++) {
  137. var lfLayer = graph.childNodes[i];
  138. // 只保留包含节点和边的基础图层进行下载,其他图层删除
  139. var layerClassList = lfLayer.classList && Array.from(lfLayer.classList);
  140. if (layerClassList && layerClassList.indexOf('lf-base') < 0) {
  141. graph.removeChild(graph.childNodes[i]);
  142. childLength--;
  143. i--;
  144. }
  145. else {
  146. // 删除锚点
  147. var lfBase = graph.childNodes[i];
  148. lfBase && lfBase.childNodes.forEach(function (item) {
  149. var element = item;
  150. _this.removeAnchor(element.firstChild);
  151. });
  152. }
  153. }
  154. }
  155. // offset值加10,保证图形不会紧贴着下载图片的左边和上边
  156. copy.lastChild.style.transform = "matrix(1, 0, 0, 1, " + (-this.offsetX + 10) + ", " + (-this.offsetY + 10) + ")";
  157. var dpr = window.devicePixelRatio || 1;
  158. var canvas = document.createElement('canvas');
  159. /*
  160. 为了计算真实宽高需要取图的真实dom
  161. 真实dom存在缩放影响其宽高数值
  162. 在得到真实宽高后除以缩放比例即可得到正常宽高
  163. */
  164. var base = this.lf.graphModel.rootEl.querySelector('.lf-base');
  165. var bbox = base.getBoundingClientRect();
  166. var graphModel = this.lf.graphModel;
  167. var transformModel = graphModel.transformModel;
  168. var SCALE_X = transformModel.SCALE_X, SCALE_Y = transformModel.SCALE_Y;
  169. var bboxWidth = Math.ceil(bbox.width / SCALE_X);
  170. var bboxHeight = Math.ceil(bbox.height / SCALE_Y);
  171. // width,height 值加40,保证图形不会紧贴着下载图片的右边和下边
  172. canvas.style.width = bboxWidth + "px";
  173. canvas.style.height = bboxHeight + "px";
  174. canvas.width = bboxWidth * dpr + 80;
  175. canvas.height = bboxHeight * dpr + 80;
  176. var ctx = canvas.getContext('2d');
  177. ctx.clearRect(0, 0, canvas.width, canvas.height);
  178. ctx.scale(dpr, dpr);
  179. // 如果有背景色,设置流程图导出的背景色
  180. if (backgroundColor) {
  181. ctx.fillStyle = backgroundColor;
  182. ctx.fillRect(0, 0, bboxWidth * dpr + 80, bboxHeight * dpr + 80);
  183. }
  184. else {
  185. ctx.clearRect(0, 0, bboxWidth, bboxHeight);
  186. }
  187. var img = new Image();
  188. var style = document.createElement('style');
  189. style.innerHTML = this.getClassRules();
  190. var foreignObject = document.createElement('foreignObject');
  191. foreignObject.appendChild(style);
  192. copy.appendChild(foreignObject);
  193. return new Promise(function (resolve) {
  194. img.onload = function () {
  195. ctx.drawImage(img, 0, 0);
  196. resolve(canvas);
  197. };
  198. /*
  199. 因为svg中存在dom存放在foreignObject元素中
  200. SVG图形转成img对象
  201. todo: 会导致一些清晰度问题这个需要再解决
  202. fixme: XMLSerializer的中的css background url不会下载图片
  203. */
  204. var svg2Img = "data:image/svg+xml;charset=utf-8," + new XMLSerializer().serializeToString(copy);
  205. var imgSrc = svg2Img.replace(/\n/g, '').replace(/\t/g, '').replace(/#/g, '%23');
  206. img.src = imgSrc;
  207. });
  208. };
  209. Snapshot.pluginName = 'snapshot';
  210. return Snapshot;
  211. }());
  212. export default Snapshot;
  213. export { Snapshot, };