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