@logicflow/extension 2.0.17 → 2.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +6 -0
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/components/highlight/index.js +19 -3
- package/es/dynamic-group/index.js +0 -2
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/tools/proximity-connect/index.js +25 -4
- package/es/tools/snapshot/index.d.ts +47 -20
- package/es/tools/snapshot/index.js +459 -246
- package/lib/components/highlight/index.js +18 -2
- package/lib/dynamic-group/index.js +0 -2
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/tools/proximity-connect/index.js +24 -3
- package/lib/tools/snapshot/index.d.ts +47 -20
- package/lib/tools/snapshot/index.js +459 -246
- package/package.json +1 -1
- package/src/components/highlight/index.ts +30 -5
- package/src/dynamic-group/index.ts +0 -3
- package/src/style/raw.ts +4 -0
- package/src/tools/proximity-connect/index.ts +30 -3
- package/src/tools/snapshot/index.ts +325 -152
- package/stats.html +1 -1
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
14
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
15
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -62,9 +73,10 @@ var Snapshot = /** @class */ (function () {
|
|
|
62
73
|
}
|
|
63
74
|
}); }); };
|
|
64
75
|
/* 获取Blob对象 */
|
|
65
|
-
lf.getSnapshotBlob = function (backgroundColor,
|
|
76
|
+
lf.getSnapshotBlob = function (backgroundColor, // 兼容老的使用方式
|
|
77
|
+
fileType, toImageOptions) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
66
78
|
switch (_a.label) {
|
|
67
|
-
case 0: return [4 /*yield*/, this.getSnapshotBlob(backgroundColor, fileType)
|
|
79
|
+
case 0: return [4 /*yield*/, this.getSnapshotBlob(backgroundColor, fileType, toImageOptions)
|
|
68
80
|
/* 获取Base64对象 */
|
|
69
81
|
];
|
|
70
82
|
case 1: return [2 /*return*/, _a.sent()
|
|
@@ -73,9 +85,10 @@ var Snapshot = /** @class */ (function () {
|
|
|
73
85
|
}
|
|
74
86
|
}); }); };
|
|
75
87
|
/* 获取Base64对象 */
|
|
76
|
-
lf.getSnapshotBase64 = function (backgroundColor,
|
|
88
|
+
lf.getSnapshotBase64 = function (backgroundColor, // 兼容老的使用方式
|
|
89
|
+
fileType, toImageOptions) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
77
90
|
switch (_a.label) {
|
|
78
|
-
case 0: return [4 /*yield*/, this.getSnapshotBase64(backgroundColor, fileType)];
|
|
91
|
+
case 0: return [4 /*yield*/, this.getSnapshotBase64(backgroundColor, fileType, toImageOptions)];
|
|
79
92
|
case 1: return [2 /*return*/, _a.sent()];
|
|
80
93
|
}
|
|
81
94
|
}); }); };
|
|
@@ -140,13 +153,329 @@ var Snapshot = /** @class */ (function () {
|
|
|
140
153
|
}
|
|
141
154
|
};
|
|
142
155
|
/**
|
|
143
|
-
*
|
|
144
|
-
* @param
|
|
145
|
-
* @
|
|
156
|
+
* 将图片转换为base64格式
|
|
157
|
+
* @param url - 图片URL
|
|
158
|
+
* @returns Promise<string> - base64字符串
|
|
146
159
|
*/
|
|
147
|
-
Snapshot.prototype.
|
|
160
|
+
Snapshot.prototype.convertImageToBase64 = function (url) {
|
|
148
161
|
return __awaiter(this, void 0, void 0, function () {
|
|
149
|
-
|
|
162
|
+
return __generator(this, function (_a) {
|
|
163
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
164
|
+
var img = new Image();
|
|
165
|
+
img.crossOrigin = 'anonymous'; // 处理跨域问题
|
|
166
|
+
img.onload = function () {
|
|
167
|
+
var canvas = document.createElement('canvas');
|
|
168
|
+
canvas.width = img.width;
|
|
169
|
+
canvas.height = img.height;
|
|
170
|
+
var ctx = canvas.getContext('2d');
|
|
171
|
+
ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(img, 0, 0);
|
|
172
|
+
var base64 = canvas.toDataURL('image/png');
|
|
173
|
+
resolve(base64);
|
|
174
|
+
};
|
|
175
|
+
img.onerror = function () {
|
|
176
|
+
reject(new Error("Failed to load image: ".concat(url)));
|
|
177
|
+
};
|
|
178
|
+
img.src = url;
|
|
179
|
+
})];
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* 检查URL是否为相对路径
|
|
185
|
+
* @param url - 要检查的URL
|
|
186
|
+
* @returns boolean - 是否为相对路径
|
|
187
|
+
*/
|
|
188
|
+
Snapshot.prototype.isRelativePath = function (url) {
|
|
189
|
+
return (!url.startsWith('data:') &&
|
|
190
|
+
!url.startsWith('http://') &&
|
|
191
|
+
!url.startsWith('https://') &&
|
|
192
|
+
!url.startsWith('//'));
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* 处理SVG中的图片元素
|
|
196
|
+
* @param element - SVG元素
|
|
197
|
+
*/
|
|
198
|
+
Snapshot.prototype.processImages = function (element) {
|
|
199
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
200
|
+
var images, i, image, href, base64, error_1, foreignObjects, i, foreignObject, images_1, j, image, src, base64, error_2;
|
|
201
|
+
return __generator(this, function (_a) {
|
|
202
|
+
switch (_a.label) {
|
|
203
|
+
case 0:
|
|
204
|
+
images = element.getElementsByTagName('image');
|
|
205
|
+
i = 0;
|
|
206
|
+
_a.label = 1;
|
|
207
|
+
case 1:
|
|
208
|
+
if (!(i < images.length)) return [3 /*break*/, 6];
|
|
209
|
+
image = images[i];
|
|
210
|
+
href = image.getAttributeNS('http://www.w3.org/1999/xlink', 'href') ||
|
|
211
|
+
image.getAttribute('href');
|
|
212
|
+
if (!(href && this.isRelativePath(href))) return [3 /*break*/, 5];
|
|
213
|
+
_a.label = 2;
|
|
214
|
+
case 2:
|
|
215
|
+
_a.trys.push([2, 4, , 5]);
|
|
216
|
+
return [4 /*yield*/, this.convertImageToBase64(href)];
|
|
217
|
+
case 3:
|
|
218
|
+
base64 = _a.sent();
|
|
219
|
+
image.setAttributeNS('http://www.w3.org/1999/xlink', 'href', base64);
|
|
220
|
+
image.setAttribute('href', base64);
|
|
221
|
+
return [3 /*break*/, 5];
|
|
222
|
+
case 4:
|
|
223
|
+
error_1 = _a.sent();
|
|
224
|
+
console.warn("Failed to convert image to base64: ".concat(href), error_1);
|
|
225
|
+
return [3 /*break*/, 5];
|
|
226
|
+
case 5:
|
|
227
|
+
i++;
|
|
228
|
+
return [3 /*break*/, 1];
|
|
229
|
+
case 6:
|
|
230
|
+
foreignObjects = element.getElementsByTagName('foreignObject');
|
|
231
|
+
i = 0;
|
|
232
|
+
_a.label = 7;
|
|
233
|
+
case 7:
|
|
234
|
+
if (!(i < foreignObjects.length)) return [3 /*break*/, 14];
|
|
235
|
+
foreignObject = foreignObjects[i];
|
|
236
|
+
images_1 = foreignObject.getElementsByTagName('img');
|
|
237
|
+
j = 0;
|
|
238
|
+
_a.label = 8;
|
|
239
|
+
case 8:
|
|
240
|
+
if (!(j < images_1.length)) return [3 /*break*/, 13];
|
|
241
|
+
image = images_1[j];
|
|
242
|
+
src = image.getAttribute('src');
|
|
243
|
+
if (!(src && this.isRelativePath(src))) return [3 /*break*/, 12];
|
|
244
|
+
_a.label = 9;
|
|
245
|
+
case 9:
|
|
246
|
+
_a.trys.push([9, 11, , 12]);
|
|
247
|
+
return [4 /*yield*/, this.convertImageToBase64(src)];
|
|
248
|
+
case 10:
|
|
249
|
+
base64 = _a.sent();
|
|
250
|
+
image.setAttribute('src', base64);
|
|
251
|
+
return [3 /*break*/, 12];
|
|
252
|
+
case 11:
|
|
253
|
+
error_2 = _a.sent();
|
|
254
|
+
console.warn("Failed to convert image to base64: ".concat(src), error_2);
|
|
255
|
+
return [3 /*break*/, 12];
|
|
256
|
+
case 12:
|
|
257
|
+
j++;
|
|
258
|
+
return [3 /*break*/, 8];
|
|
259
|
+
case 13:
|
|
260
|
+
i++;
|
|
261
|
+
return [3 /*break*/, 7];
|
|
262
|
+
case 14: return [2 /*return*/];
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* 克隆并处理画布节点
|
|
269
|
+
* @param svg
|
|
270
|
+
* @returns
|
|
271
|
+
*/
|
|
272
|
+
Snapshot.prototype.cloneSvg = function (svg_1) {
|
|
273
|
+
return __awaiter(this, arguments, void 0, function (svg, addStyle) {
|
|
274
|
+
var copy, graph, childLength, i, lfLayer, layerClassList, lfBase, style, foreignObject;
|
|
275
|
+
var _this = this;
|
|
276
|
+
var _a;
|
|
277
|
+
if (addStyle === void 0) { addStyle = true; }
|
|
278
|
+
return __generator(this, function (_b) {
|
|
279
|
+
switch (_b.label) {
|
|
280
|
+
case 0:
|
|
281
|
+
copy = svg.cloneNode(true);
|
|
282
|
+
graph = copy.lastChild;
|
|
283
|
+
childLength = (_a = graph === null || graph === void 0 ? void 0 : graph.childNodes) === null || _a === void 0 ? void 0 : _a.length;
|
|
284
|
+
if (childLength) {
|
|
285
|
+
for (i = 0; i < childLength; i++) {
|
|
286
|
+
lfLayer = graph === null || graph === void 0 ? void 0 : graph.childNodes[i];
|
|
287
|
+
layerClassList = lfLayer.classList && Array.from(lfLayer.classList);
|
|
288
|
+
if (layerClassList && layerClassList.indexOf('lf-base') < 0) {
|
|
289
|
+
graph === null || graph === void 0 ? void 0 : graph.removeChild(graph.childNodes[i]);
|
|
290
|
+
childLength--;
|
|
291
|
+
i--;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
lfBase = graph === null || graph === void 0 ? void 0 : graph.childNodes[i];
|
|
295
|
+
lfBase &&
|
|
296
|
+
lfBase.childNodes.forEach(function (item) {
|
|
297
|
+
var element = item;
|
|
298
|
+
_this.removeAnchor(element.firstChild);
|
|
299
|
+
_this.removeRotateControl(element.firstChild);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// 处理图片路径
|
|
305
|
+
return [4 /*yield*/, this.processImages(copy)
|
|
306
|
+
// 设置css样式
|
|
307
|
+
];
|
|
308
|
+
case 1:
|
|
309
|
+
// 处理图片路径
|
|
310
|
+
_b.sent();
|
|
311
|
+
// 设置css样式
|
|
312
|
+
if (addStyle) {
|
|
313
|
+
style = document.createElement('style');
|
|
314
|
+
style.innerHTML = this.getClassRules();
|
|
315
|
+
foreignObject = document.createElement('foreignObject');
|
|
316
|
+
foreignObject.appendChild(style);
|
|
317
|
+
copy.appendChild(foreignObject);
|
|
318
|
+
}
|
|
319
|
+
return [2 /*return*/, copy];
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
/**
|
|
325
|
+
* 获取脚本 css 样式
|
|
326
|
+
* @returns
|
|
327
|
+
*/
|
|
328
|
+
Snapshot.prototype.getClassRules = function () {
|
|
329
|
+
var rules = '';
|
|
330
|
+
if (this.useGlobalRules) {
|
|
331
|
+
var styleSheets = document.styleSheets;
|
|
332
|
+
for (var i = 0; i < styleSheets.length; i++) {
|
|
333
|
+
var sheet = styleSheets[i];
|
|
334
|
+
// 这里是为了过滤掉不同源 css 脚本,防止报错终止导出
|
|
335
|
+
try {
|
|
336
|
+
for (var j = 0; j < sheet.cssRules.length; j++) {
|
|
337
|
+
rules += sheet.cssRules[j].cssText;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
console.log('CSS scripts from different sources have been filtered out');
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (this.customCssRules) {
|
|
346
|
+
rules += this.customCssRules;
|
|
347
|
+
}
|
|
348
|
+
return rules;
|
|
349
|
+
};
|
|
350
|
+
/**
|
|
351
|
+
* 将 svg 转化为 canvas
|
|
352
|
+
* @param svg - svg 元素
|
|
353
|
+
* @param toImageOptions - 图像选项
|
|
354
|
+
* @returns Promise<canvas> - 返回 canvas 对象
|
|
355
|
+
*/
|
|
356
|
+
Snapshot.prototype.getCanvasData = function (svg, toImageOptions) {
|
|
357
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
358
|
+
var width, height, backgroundColor, _a, padding, copy, dpr, base, bbox, layoutCanvas, layout, offsetX, offsetY, graphModel, transformModel, SCALE_X, SCALE_Y, TRANSLATE_X, TRANSLATE_Y, safetyFactor, actualWidth, actualHeight, bboxWidth, bboxHeight, canvas, safetyMargin, ctx, img, style, foreignObject;
|
|
359
|
+
return __generator(this, function (_b) {
|
|
360
|
+
switch (_b.label) {
|
|
361
|
+
case 0:
|
|
362
|
+
width = toImageOptions.width, height = toImageOptions.height, backgroundColor = toImageOptions.backgroundColor, _a = toImageOptions.padding, padding = _a === void 0 ? 40 : _a;
|
|
363
|
+
return [4 /*yield*/, this.cloneSvg(svg, false)];
|
|
364
|
+
case 1:
|
|
365
|
+
copy = _b.sent();
|
|
366
|
+
dpr = window.devicePixelRatio || 1;
|
|
367
|
+
if (dpr < 1) {
|
|
368
|
+
// https://github.com/didi/LogicFlow/issues/1222
|
|
369
|
+
// canvas.width = bboxWidth * dpr配合ctx.scale(dpr, dpr)是为了解决绘制模糊
|
|
370
|
+
// 比如dpr=2,先让canvas.width放大到等同于屏幕的物理像素宽高,然后自适应缩放适配canvas.style.width
|
|
371
|
+
// 由于所有元素都缩放了一半,因此需要ctx.scale(dpr, dpr)放大2倍整体绘制的内容
|
|
372
|
+
// 当用户缩放浏览器时,window.devicePixelRatio会随着变小
|
|
373
|
+
// 当window.devicePixelRatio变小到一定程度,会导致canvas.width<canvas.style.width
|
|
374
|
+
// 由于导出图片的svg的大小是canvas.style.width+canvas.style.height
|
|
375
|
+
// 因此会导致导出的svg图片无法完整绘制到canvas(因为canvas.width小于svg的宽)
|
|
376
|
+
// 从而导致canvas导出图片是缺失的svg
|
|
377
|
+
// 而dpr>=1就能保证canvas.width>=canvas.style.width
|
|
378
|
+
// 当dpr小于1的时候,我们强制转化为1,并不会产生绘制模糊等问题
|
|
379
|
+
dpr = 1;
|
|
380
|
+
}
|
|
381
|
+
base = this.lf.graphModel.rootEl.querySelector('.lf-base');
|
|
382
|
+
bbox = base.getBoundingClientRect();
|
|
383
|
+
layoutCanvas = this.lf.container.querySelector('.lf-canvas-overlay');
|
|
384
|
+
layout = layoutCanvas.getBoundingClientRect();
|
|
385
|
+
offsetX = bbox.x - layout.x;
|
|
386
|
+
offsetY = bbox.y - layout.y;
|
|
387
|
+
graphModel = this.lf.graphModel;
|
|
388
|
+
transformModel = graphModel.transformModel;
|
|
389
|
+
SCALE_X = transformModel.SCALE_X, SCALE_Y = transformModel.SCALE_Y, TRANSLATE_X = transformModel.TRANSLATE_X, TRANSLATE_Y = transformModel.TRANSLATE_Y;
|
|
390
|
+
safetyFactor = 1.1 // 安全系数,增加20%的空间
|
|
391
|
+
;
|
|
392
|
+
actualWidth = (bbox.width / SCALE_X) * safetyFactor;
|
|
393
|
+
actualHeight = (bbox.height / SCALE_Y) * safetyFactor;
|
|
394
|
+
copy.lastChild.style.transform = "matrix(1, 0, 0, 1, ".concat((-offsetX + TRANSLATE_X) * (1 / SCALE_X) + padding / dpr, ", ").concat((-offsetY + TRANSLATE_Y) * (1 / SCALE_Y) + padding / dpr, ")");
|
|
395
|
+
bboxWidth = Math.ceil(actualWidth);
|
|
396
|
+
bboxHeight = Math.ceil(actualHeight);
|
|
397
|
+
canvas = document.createElement('canvas');
|
|
398
|
+
canvas.style.width = "".concat(bboxWidth, "px");
|
|
399
|
+
canvas.style.height = "".concat(bboxHeight, "px");
|
|
400
|
+
safetyMargin = 40 // 额外的安全边距
|
|
401
|
+
;
|
|
402
|
+
canvas.width = bboxWidth * dpr + padding * 2 + safetyMargin;
|
|
403
|
+
canvas.height = bboxHeight * dpr + padding * 2 + safetyMargin;
|
|
404
|
+
ctx = canvas.getContext('2d');
|
|
405
|
+
if (ctx) {
|
|
406
|
+
// 清空canvas
|
|
407
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
408
|
+
ctx.scale(dpr, dpr);
|
|
409
|
+
// 如果有背景色,设置流程图导出的背景色
|
|
410
|
+
if (backgroundColor) {
|
|
411
|
+
ctx.fillStyle = backgroundColor;
|
|
412
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
img = new Image();
|
|
419
|
+
style = document.createElement('style');
|
|
420
|
+
style.innerHTML = this.getClassRules();
|
|
421
|
+
foreignObject = document.createElement('foreignObject');
|
|
422
|
+
foreignObject.appendChild(style);
|
|
423
|
+
copy.appendChild(foreignObject);
|
|
424
|
+
return [2 /*return*/, new Promise(function (resolve) {
|
|
425
|
+
img.onload = function () {
|
|
426
|
+
var isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
|
|
427
|
+
try {
|
|
428
|
+
if (isFirefox) {
|
|
429
|
+
createImageBitmap(img, {
|
|
430
|
+
resizeWidth: width && height
|
|
431
|
+
? (0, utils_1.copyCanvas)(canvas, width, height).width
|
|
432
|
+
: canvas.width,
|
|
433
|
+
resizeHeight: width && height
|
|
434
|
+
? (0, utils_1.copyCanvas)(canvas, width, height).height
|
|
435
|
+
: canvas.height,
|
|
436
|
+
}).then(function (imageBitmap) {
|
|
437
|
+
// 由于在transform矩阵中已经考虑了padding,这里不再需要额外的padding偏移
|
|
438
|
+
ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(imageBitmap, 0, 0);
|
|
439
|
+
resolve(width && height ? (0, utils_1.copyCanvas)(canvas, width, height) : canvas);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
// 由于在transform矩阵中已经考虑了padding,这里不再需要额外的padding偏移
|
|
444
|
+
ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(img, 0, 0);
|
|
445
|
+
resolve(width && height ? (0, utils_1.copyCanvas)(canvas, width, height) : canvas);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
// 由于在transform矩阵中已经考虑了padding,这里不再需要额外的padding偏移
|
|
450
|
+
ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(img, 0, 0);
|
|
451
|
+
resolve(width && height ? (0, utils_1.copyCanvas)(canvas, width, height) : canvas);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
/*
|
|
455
|
+
因为svg中存在dom存放在foreignObject元素中
|
|
456
|
+
svg dom => Base64编码字符串 挂载到img上
|
|
457
|
+
fixme: XMLSerializer的中的css background url不会下载图片
|
|
458
|
+
*/
|
|
459
|
+
var svg2Img = "data:image/svg+xml;charset=utf-8,".concat(new XMLSerializer().serializeToString(copy));
|
|
460
|
+
var imgSrc = svg2Img
|
|
461
|
+
.replace(/\n/g, '')
|
|
462
|
+
.replace(/\t/g, '')
|
|
463
|
+
.replace(/#/g, '%23');
|
|
464
|
+
img.src = imgSrc;
|
|
465
|
+
})];
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* 封装导出前的通用处理逻辑:局部渲染模式处理、静默模式处理
|
|
472
|
+
* @param callback 实际执行的导出操作回调函数
|
|
473
|
+
* @param toImageOptions 导出图片选项
|
|
474
|
+
* @returns 返回回调函数的执行结果
|
|
475
|
+
*/
|
|
476
|
+
Snapshot.prototype.withExportPreparation = function (callback, toImageOptions) {
|
|
477
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
478
|
+
var curPartial, _a, partial, editConfig, result;
|
|
150
479
|
var _this = this;
|
|
151
480
|
return __generator(this, function (_b) {
|
|
152
481
|
switch (_b.label) {
|
|
@@ -160,30 +489,61 @@ var Snapshot = /** @class */ (function () {
|
|
|
160
489
|
stopScrollGraph: true,
|
|
161
490
|
stopMoveGraph: true,
|
|
162
491
|
});
|
|
163
|
-
|
|
492
|
+
_b.label = 1;
|
|
493
|
+
case 1:
|
|
494
|
+
_b.trys.push([1, , 6, 7]);
|
|
495
|
+
if (!(curPartial !== partial)) return [3 /*break*/, 3];
|
|
164
496
|
this.lf.graphModel.setPartial(partial);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
497
|
+
return [4 /*yield*/, new Promise(function (resolve) {
|
|
498
|
+
_this.lf.graphModel.eventCenter.once('graph:updated', function () { return __awaiter(_this, void 0, void 0, function () {
|
|
499
|
+
var callbackResult;
|
|
500
|
+
return __generator(this, function (_a) {
|
|
501
|
+
switch (_a.label) {
|
|
502
|
+
case 0: return [4 /*yield*/, callback()
|
|
503
|
+
// 恢复原来渲染模式
|
|
504
|
+
];
|
|
505
|
+
case 1:
|
|
506
|
+
callbackResult = _a.sent();
|
|
507
|
+
// 恢复原来渲染模式
|
|
508
|
+
this.lf.graphModel.setPartial(curPartial);
|
|
509
|
+
resolve(callbackResult);
|
|
510
|
+
return [2 /*return*/];
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
}); });
|
|
514
|
+
})];
|
|
181
515
|
case 2:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
516
|
+
// 等待画布更新完成
|
|
517
|
+
result = _b.sent();
|
|
518
|
+
return [3 /*break*/, 5];
|
|
519
|
+
case 3: return [4 /*yield*/, callback()];
|
|
520
|
+
case 4:
|
|
521
|
+
// 直接执行回调
|
|
522
|
+
result = _b.sent();
|
|
523
|
+
_b.label = 5;
|
|
524
|
+
case 5: return [3 /*break*/, 7];
|
|
525
|
+
case 6:
|
|
185
526
|
// 恢复原来配置
|
|
186
527
|
this.lf.updateEditConfig(editConfig);
|
|
528
|
+
return [7 /*endfinally*/];
|
|
529
|
+
case 7: return [2 /*return*/, result];
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
};
|
|
534
|
+
/**
|
|
535
|
+
* 导出画布:导出前的处理画布工作,局部渲染模式处理、静默模式处理
|
|
536
|
+
* @param fileName
|
|
537
|
+
* @param toImageOptions
|
|
538
|
+
*/
|
|
539
|
+
Snapshot.prototype.getSnapshot = function (fileName, toImageOptions) {
|
|
540
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
541
|
+
var _this = this;
|
|
542
|
+
return __generator(this, function (_a) {
|
|
543
|
+
switch (_a.label) {
|
|
544
|
+
case 0: return [4 /*yield*/, this.withExportPreparation(function () { return _this.snapshot(fileName, toImageOptions); }, toImageOptions)];
|
|
545
|
+
case 1:
|
|
546
|
+
_a.sent();
|
|
187
547
|
return [2 /*return*/];
|
|
188
548
|
}
|
|
189
549
|
});
|
|
@@ -207,80 +567,63 @@ var Snapshot = /** @class */ (function () {
|
|
|
207
567
|
return [4 /*yield*/, (0, utils_1.updateImageSource)(svg)];
|
|
208
568
|
case 1:
|
|
209
569
|
_c.sent();
|
|
210
|
-
if (fileType === 'svg')
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
570
|
+
if (!(fileType === 'svg')) return [3 /*break*/, 3];
|
|
571
|
+
return [4 /*yield*/, this.cloneSvg(svg)];
|
|
572
|
+
case 2:
|
|
573
|
+
copy = _c.sent();
|
|
574
|
+
svgString = new XMLSerializer().serializeToString(copy);
|
|
575
|
+
blob = new Blob([svgString], {
|
|
576
|
+
type: 'image/svg+xml;charset=utf-8',
|
|
577
|
+
});
|
|
578
|
+
url = URL.createObjectURL(blob);
|
|
579
|
+
this.triggerDownload(url);
|
|
580
|
+
return [3 /*break*/, 4];
|
|
581
|
+
case 3:
|
|
582
|
+
this.getCanvasData(svg, toImageOptions !== null && toImageOptions !== void 0 ? toImageOptions : {}).then(function (canvas) {
|
|
583
|
+
// canvas元素 => base64 url image/octet-stream: 确保所有浏览器都能正常下载
|
|
584
|
+
var imgUrl = canvas
|
|
585
|
+
.toDataURL("image/".concat(fileType), quality)
|
|
586
|
+
.replace("image/".concat(fileType), 'image/octet-stream');
|
|
587
|
+
_this.triggerDownload(imgUrl);
|
|
588
|
+
});
|
|
589
|
+
_c.label = 4;
|
|
590
|
+
case 4: return [2 /*return*/];
|
|
229
591
|
}
|
|
230
592
|
});
|
|
231
593
|
});
|
|
232
594
|
};
|
|
233
595
|
/**
|
|
234
|
-
* 获取
|
|
235
|
-
* @param backgroundColor
|
|
596
|
+
* 获取Blob对象
|
|
236
597
|
* @param fileType
|
|
598
|
+
* @param toImageOptions
|
|
237
599
|
* @returns
|
|
238
600
|
*/
|
|
239
|
-
Snapshot.prototype.
|
|
601
|
+
Snapshot.prototype.getSnapshotBlob = function (backgroundColor, fileType, toImageOptions) {
|
|
240
602
|
return __awaiter(this, void 0, void 0, function () {
|
|
241
|
-
var svg;
|
|
242
603
|
var _this = this;
|
|
243
604
|
return __generator(this, function (_a) {
|
|
244
605
|
switch (_a.label) {
|
|
245
|
-
case 0:
|
|
246
|
-
|
|
247
|
-
return [4 /*yield*/, (0, utils_1.updateImageSource)(svg)];
|
|
248
|
-
case 1:
|
|
249
|
-
_a.sent();
|
|
250
|
-
return [2 /*return*/, new Promise(function (resolve) {
|
|
251
|
-
_this.getCanvasData(svg, { backgroundColor: backgroundColor }).then(function (canvas) {
|
|
252
|
-
var base64 = canvas.toDataURL("image/".concat(fileType !== null && fileType !== void 0 ? fileType : 'png'));
|
|
253
|
-
// 输出图片数据以及图片宽高
|
|
254
|
-
resolve({
|
|
255
|
-
data: base64,
|
|
256
|
-
width: canvas.width,
|
|
257
|
-
height: canvas.height,
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
})];
|
|
606
|
+
case 0: return [4 /*yield*/, this.withExportPreparation(function () { return _this.snapshotBlob(toImageOptions, fileType, backgroundColor); }, toImageOptions)];
|
|
607
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
261
608
|
}
|
|
262
609
|
});
|
|
263
610
|
});
|
|
264
611
|
};
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
* @param backgroundColor
|
|
268
|
-
* @param fileType
|
|
269
|
-
* @returns
|
|
270
|
-
*/
|
|
271
|
-
Snapshot.prototype.getSnapshotBlob = function (backgroundColor, fileType) {
|
|
612
|
+
// 内部方法处理blob转换
|
|
613
|
+
Snapshot.prototype.snapshotBlob = function (toImageOptions, baseFileType, backgroundColor) {
|
|
272
614
|
return __awaiter(this, void 0, void 0, function () {
|
|
273
|
-
var svg;
|
|
615
|
+
var _a, fileType, svg;
|
|
274
616
|
var _this = this;
|
|
275
|
-
return __generator(this, function (
|
|
276
|
-
switch (
|
|
617
|
+
return __generator(this, function (_b) {
|
|
618
|
+
switch (_b.label) {
|
|
277
619
|
case 0:
|
|
620
|
+
_a = (toImageOptions !== null && toImageOptions !== void 0 ? toImageOptions : {}).fileType, fileType = _a === void 0 ? baseFileType : _a;
|
|
278
621
|
svg = this.getSvgRootElement(this.lf);
|
|
279
622
|
return [4 /*yield*/, (0, utils_1.updateImageSource)(svg)];
|
|
280
623
|
case 1:
|
|
281
|
-
|
|
624
|
+
_b.sent();
|
|
282
625
|
return [2 /*return*/, new Promise(function (resolve) {
|
|
283
|
-
_this.getCanvasData(svg, { backgroundColor: backgroundColor }).then(function (canvas) {
|
|
626
|
+
_this.getCanvasData(svg, __assign({ backgroundColor: backgroundColor }, (toImageOptions !== null && toImageOptions !== void 0 ? toImageOptions : {}))).then(function (canvas) {
|
|
284
627
|
canvas.toBlob(function (blob) {
|
|
285
628
|
// 输出图片数据以及图片宽高
|
|
286
629
|
resolve({
|
|
@@ -296,182 +639,52 @@ var Snapshot = /** @class */ (function () {
|
|
|
296
639
|
});
|
|
297
640
|
};
|
|
298
641
|
/**
|
|
299
|
-
*
|
|
642
|
+
* 获取base64对象
|
|
643
|
+
* @param backgroundColor
|
|
644
|
+
* @param fileType
|
|
645
|
+
* @param toImageOptions
|
|
300
646
|
* @returns
|
|
301
647
|
*/
|
|
302
|
-
Snapshot.prototype.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
rules += sheet.cssRules[j].cssText;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
catch (error) {
|
|
315
|
-
console.log('CSS scripts from different sources have been filtered out');
|
|
648
|
+
Snapshot.prototype.getSnapshotBase64 = function (backgroundColor, fileType, toImageOptions) {
|
|
649
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
650
|
+
var _this = this;
|
|
651
|
+
return __generator(this, function (_a) {
|
|
652
|
+
switch (_a.label) {
|
|
653
|
+
case 0:
|
|
654
|
+
console.log('getSnapshotBase64---------------', backgroundColor, fileType, toImageOptions);
|
|
655
|
+
return [4 /*yield*/, this.withExportPreparation(function () { return _this._getSnapshotBase64(backgroundColor, fileType, toImageOptions); }, toImageOptions)];
|
|
656
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
316
657
|
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
if (this.customCssRules) {
|
|
320
|
-
rules += this.customCssRules;
|
|
321
|
-
}
|
|
322
|
-
return rules;
|
|
658
|
+
});
|
|
659
|
+
});
|
|
323
660
|
};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
* @param svg - svg 元素
|
|
327
|
-
* @param toImageOptions - 图像选项
|
|
328
|
-
* @returns Promise<canvas> - 返回 canvas 对象
|
|
329
|
-
*/
|
|
330
|
-
Snapshot.prototype.getCanvasData = function (svg, toImageOptions) {
|
|
661
|
+
// 内部方法处理实际的base64转换
|
|
662
|
+
Snapshot.prototype._getSnapshotBase64 = function (backgroundColor, baseFileType, toImageOptions) {
|
|
331
663
|
return __awaiter(this, void 0, void 0, function () {
|
|
332
|
-
var
|
|
664
|
+
var _a, fileType, svg;
|
|
665
|
+
var _this = this;
|
|
333
666
|
return __generator(this, function (_b) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
// 当dpr小于1的时候,我们强制转化为1,并不会产生绘制模糊等问题
|
|
349
|
-
dpr = 1;
|
|
350
|
-
}
|
|
351
|
-
base = this.lf.graphModel.rootEl.querySelector('.lf-base');
|
|
352
|
-
bbox = base.getBoundingClientRect();
|
|
353
|
-
layoutCanvas = this.lf.container.querySelector('.lf-canvas-overlay');
|
|
354
|
-
layout = layoutCanvas.getBoundingClientRect();
|
|
355
|
-
offsetX = bbox.x - layout.x;
|
|
356
|
-
offsetY = bbox.y - layout.y;
|
|
357
|
-
graphModel = this.lf.graphModel;
|
|
358
|
-
transformModel = graphModel.transformModel;
|
|
359
|
-
SCALE_X = transformModel.SCALE_X, SCALE_Y = transformModel.SCALE_Y, TRANSLATE_X = transformModel.TRANSLATE_X, TRANSLATE_Y = transformModel.TRANSLATE_Y;
|
|
360
|
-
copy.lastChild.style.transform = "matrix(1, 0, 0, 1, ".concat((-offsetX + TRANSLATE_X) * (1 / SCALE_X), ", ").concat((-offsetY + TRANSLATE_Y) * (1 / SCALE_Y), ")");
|
|
361
|
-
bboxWidth = Math.ceil(bbox.width / SCALE_X);
|
|
362
|
-
bboxHeight = Math.ceil(bbox.height / SCALE_Y);
|
|
363
|
-
canvas = document.createElement('canvas');
|
|
364
|
-
canvas.style.width = "".concat(bboxWidth, "px");
|
|
365
|
-
canvas.style.height = "".concat(bboxHeight, "px");
|
|
366
|
-
// 宽高值 默认加padding 40,保证图形不会紧贴着下载图片
|
|
367
|
-
canvas.width = bboxWidth * dpr + padding * 2;
|
|
368
|
-
canvas.height = bboxHeight * dpr + padding * 2;
|
|
369
|
-
ctx = canvas.getContext('2d');
|
|
370
|
-
if (ctx) {
|
|
371
|
-
// 清空canvas
|
|
372
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
373
|
-
ctx.scale(dpr, dpr);
|
|
374
|
-
// 如果有背景色,设置流程图导出的背景色
|
|
375
|
-
if (backgroundColor) {
|
|
376
|
-
ctx.fillStyle = backgroundColor;
|
|
377
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
378
|
-
}
|
|
379
|
-
else {
|
|
380
|
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
img = new Image();
|
|
384
|
-
style = document.createElement('style');
|
|
385
|
-
style.innerHTML = this.getClassRules();
|
|
386
|
-
foreignObject = document.createElement('foreignObject');
|
|
387
|
-
foreignObject.appendChild(style);
|
|
388
|
-
copy.appendChild(foreignObject);
|
|
389
|
-
return [2 /*return*/, new Promise(function (resolve) {
|
|
390
|
-
img.onload = function () {
|
|
391
|
-
var isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
|
|
392
|
-
try {
|
|
393
|
-
if (isFirefox) {
|
|
394
|
-
createImageBitmap(img, {
|
|
395
|
-
resizeWidth: width && height
|
|
396
|
-
? (0, utils_1.copyCanvas)(canvas, width, height).width
|
|
397
|
-
: canvas.width,
|
|
398
|
-
resizeHeight: width && height
|
|
399
|
-
? (0, utils_1.copyCanvas)(canvas, width, height).height
|
|
400
|
-
: canvas.height,
|
|
401
|
-
}).then(function (imageBitmap) {
|
|
402
|
-
ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(imageBitmap, padding / dpr, padding / dpr);
|
|
403
|
-
resolve(width && height ? (0, utils_1.copyCanvas)(canvas, width, height) : canvas);
|
|
667
|
+
switch (_b.label) {
|
|
668
|
+
case 0:
|
|
669
|
+
_a = (toImageOptions !== null && toImageOptions !== void 0 ? toImageOptions : {}).fileType, fileType = _a === void 0 ? baseFileType : _a;
|
|
670
|
+
svg = this.getSvgRootElement(this.lf);
|
|
671
|
+
return [4 /*yield*/, (0, utils_1.updateImageSource)(svg)];
|
|
672
|
+
case 1:
|
|
673
|
+
_b.sent();
|
|
674
|
+
return [2 /*return*/, new Promise(function (resolve) {
|
|
675
|
+
_this.getCanvasData(svg, __assign({ backgroundColor: backgroundColor }, (toImageOptions !== null && toImageOptions !== void 0 ? toImageOptions : {}))).then(function (canvas) {
|
|
676
|
+
var base64 = canvas.toDataURL("image/".concat(fileType !== null && fileType !== void 0 ? fileType : 'png'));
|
|
677
|
+
resolve({
|
|
678
|
+
data: base64,
|
|
679
|
+
width: canvas.width,
|
|
680
|
+
height: canvas.height,
|
|
404
681
|
});
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
resolve(width && height ? (0, utils_1.copyCanvas)(canvas, width, height) : canvas);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
catch (e) {
|
|
412
|
-
ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(img, padding / dpr, padding / dpr);
|
|
413
|
-
resolve(width && height ? (0, utils_1.copyCanvas)(canvas, width, height) : canvas);
|
|
414
|
-
}
|
|
415
|
-
};
|
|
416
|
-
/*
|
|
417
|
-
因为svg中存在dom存放在foreignObject元素中
|
|
418
|
-
svg dom => Base64编码字符串 挂载到img上
|
|
419
|
-
fixme: XMLSerializer的中的css background url不会下载图片
|
|
420
|
-
*/
|
|
421
|
-
var svg2Img = "data:image/svg+xml;charset=utf-8,".concat(new XMLSerializer().serializeToString(copy));
|
|
422
|
-
var imgSrc = svg2Img
|
|
423
|
-
.replace(/\n/g, '')
|
|
424
|
-
.replace(/\t/g, '')
|
|
425
|
-
.replace(/#/g, '%23');
|
|
426
|
-
img.src = imgSrc;
|
|
427
|
-
})];
|
|
682
|
+
});
|
|
683
|
+
})];
|
|
684
|
+
}
|
|
428
685
|
});
|
|
429
686
|
});
|
|
430
687
|
};
|
|
431
|
-
/**
|
|
432
|
-
* 克隆并处理画布节点
|
|
433
|
-
* @param svg
|
|
434
|
-
* @returns
|
|
435
|
-
*/
|
|
436
|
-
Snapshot.prototype.cloneSvg = function (svg, addStyle) {
|
|
437
|
-
var _this = this;
|
|
438
|
-
var _a;
|
|
439
|
-
if (addStyle === void 0) { addStyle = true; }
|
|
440
|
-
var copy = svg.cloneNode(true);
|
|
441
|
-
var graph = copy.lastChild;
|
|
442
|
-
var childLength = (_a = graph === null || graph === void 0 ? void 0 : graph.childNodes) === null || _a === void 0 ? void 0 : _a.length;
|
|
443
|
-
if (childLength) {
|
|
444
|
-
for (var i = 0; i < childLength; i++) {
|
|
445
|
-
var lfLayer = graph === null || graph === void 0 ? void 0 : graph.childNodes[i];
|
|
446
|
-
// 只保留包含节点和边的基础图层进行下载,其他图层删除
|
|
447
|
-
var layerClassList = lfLayer.classList && Array.from(lfLayer.classList);
|
|
448
|
-
if (layerClassList && layerClassList.indexOf('lf-base') < 0) {
|
|
449
|
-
graph === null || graph === void 0 ? void 0 : graph.removeChild(graph.childNodes[i]);
|
|
450
|
-
childLength--;
|
|
451
|
-
i--;
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
// 删除锚点
|
|
455
|
-
var lfBase = graph === null || graph === void 0 ? void 0 : graph.childNodes[i];
|
|
456
|
-
lfBase &&
|
|
457
|
-
lfBase.childNodes.forEach(function (item) {
|
|
458
|
-
var element = item;
|
|
459
|
-
_this.removeAnchor(element.firstChild);
|
|
460
|
-
_this.removeRotateControl(element.firstChild);
|
|
461
|
-
});
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
// 设置css样式
|
|
466
|
-
if (addStyle) {
|
|
467
|
-
var style = document.createElement('style');
|
|
468
|
-
style.innerHTML = this.getClassRules();
|
|
469
|
-
var foreignObject = document.createElement('foreignObject');
|
|
470
|
-
foreignObject.appendChild(style);
|
|
471
|
-
copy.appendChild(foreignObject);
|
|
472
|
-
}
|
|
473
|
-
return copy;
|
|
474
|
-
};
|
|
475
688
|
Snapshot.pluginName = 'snapshot';
|
|
476
689
|
return Snapshot;
|
|
477
690
|
}());
|