@logicflow/extension 2.2.0-alpha.4 → 2.2.0-alpha.5

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.
@@ -315,31 +315,34 @@ export class Snapshot {
315
315
  }
316
316
 
317
317
  /**
318
- * 根据浏览器类型获取Canvas尺寸限制
319
- * @returns 包含最大主维度和次维度的对象
318
+ * 根据浏览器对 canvas 的大小限制,计算等比缩放比例
319
+ * - 参考 MDN 最大的画布尺寸:
320
+ * https://developer.mozilla.org/zh-CN/docs/Web/HTML/Reference/Elements/canvas#最大的画布尺寸
321
+ *
322
+ * @param width
323
+ * @param height
320
324
  */
321
- private getCanvasDimensionsByBrowser(): {
322
- maxCanvasDimension: number
323
- otherMaxCanvasDimension: number
324
- } {
325
- const userAgent = navigator.userAgent
325
+ private getCanvasScaleRatio(width: number, height: number): number {
326
+ /* 单边最大像素 */
327
+ const maxCanvasSide = 32767
328
+ /* 最大像素面积 */
329
+ const maxCanvasArea = 268435456
326
330
 
327
- // 默认值
328
- let maxCanvasDimension = 65535
329
- let otherMaxCanvasDimension = 4096
331
+ const area = width * height
330
332
 
331
333
  if (
332
- userAgent.indexOf('Chrome') !== -1 ||
333
- userAgent.indexOf('Edge') !== -1
334
+ width <= maxCanvasSide &&
335
+ height <= maxCanvasSide &&
336
+ area <= maxCanvasArea
334
337
  ) {
335
- maxCanvasDimension = 65535
336
- otherMaxCanvasDimension = 4096
337
- } else if (userAgent.indexOf('Firefox') !== -1) {
338
- maxCanvasDimension = 32767
339
- otherMaxCanvasDimension = 3814
338
+ return 1
340
339
  }
341
340
 
342
- return { maxCanvasDimension, otherMaxCanvasDimension }
341
+ const widthScale = maxCanvasSide / width
342
+ const heightScale = maxCanvasSide / height
343
+ const areaScale = maxCanvasArea / area
344
+
345
+ return Math.min(widthScale, heightScale, areaScale)
343
346
  }
344
347
 
345
348
  /**
@@ -389,76 +392,50 @@ export class Snapshot {
389
392
  // 计算实际宽高,考虑缩放因素
390
393
  // 在宽画布情况下,getBoundingClientRect可能无法获取到所有元素的边界
391
394
  // 因此我们添加一个安全系数来确保能够容纳所有元素
392
- const safetyFactor = toImageOptions.safetyFactor || 1.1 // 安全系数,增加10%的空间
393
- const actualWidth = (bbox.width / SCALE_X) * safetyFactor
394
- const actualHeight = (bbox.height / SCALE_Y) * safetyFactor
395
+ const safetyFactor = toImageOptions.safetyFactor || 1 // 安全系数,增加10%的空间
396
+ const actualWidth = bbox.width / SCALE_X
397
+ const actualHeight = bbox.height / SCALE_Y
398
+ const factorWidth = actualWidth * (safetyFactor - 1)
399
+ const factorHeight = actualHeight * (safetyFactor - 1)
395
400
 
396
401
  // 包含所有元素的最小宽高,确保足够大以容纳所有元素
397
- const bboxWidth = Math.ceil(actualWidth)
398
- const bboxHeight = Math.ceil(actualHeight)
402
+ const bboxWidth = Math.ceil(actualWidth + factorWidth)
403
+ const bboxHeight = Math.ceil(actualHeight + factorHeight)
399
404
  const canvas = document.createElement('canvas')
400
405
  canvas.style.width = `${bboxWidth}px`
401
406
  canvas.style.height = `${bboxHeight}px`
402
407
 
403
408
  // 宽高值 默认加padding 40,保证图形不会紧贴着下载图片
404
409
  // 为宽画布添加额外的安全边距,确保不会裁剪
405
- const safetyMargin = toImageOptions.safetyMargin || 40 // 额外的安全边距
406
-
407
- // 获取当前浏览器类型,不同浏览器对canvas的限制不同
408
- const { maxCanvasDimension, otherMaxCanvasDimension } =
409
- this.getCanvasDimensionsByBrowser()
410
- const MAX_CANVAS_DIMENSION = maxCanvasDimension
411
- const OTHER_MAX_CANVAS_DIMENSION = otherMaxCanvasDimension
412
-
413
- let targetWidth = bboxWidth * dpr + padding * 2 + safetyMargin
414
- let targetHeight = bboxHeight * dpr + padding * 2 + safetyMargin
415
- let scaleWidth = 1 //宽 缩放
416
- let scaleHeight = 1 //高 缩放
417
- // 对宽和高分别进行缩放,如chrome,矩形单边最大宽度不超过65535,如宽超过65535,那么高不能超过4096,否则像素会超,也会显示不出。
418
- if (
419
- targetWidth > MAX_CANVAS_DIMENSION &&
420
- targetHeight > OTHER_MAX_CANVAS_DIMENSION
421
- ) {
422
- scaleWidth = MAX_CANVAS_DIMENSION / targetWidth
423
- scaleHeight = OTHER_MAX_CANVAS_DIMENSION / targetHeight
424
- } else if (
425
- targetWidth > OTHER_MAX_CANVAS_DIMENSION &&
426
- targetHeight > MAX_CANVAS_DIMENSION
427
- ) {
428
- scaleWidth = OTHER_MAX_CANVAS_DIMENSION / targetWidth
429
- scaleHeight = MAX_CANVAS_DIMENSION / targetHeight
430
- } else if (
431
- targetWidth > MAX_CANVAS_DIMENSION &&
432
- targetHeight < OTHER_MAX_CANVAS_DIMENSION
433
- ) {
434
- scaleHeight = scaleWidth = MAX_CANVAS_DIMENSION / targetWidth
435
- } else if (
436
- targetWidth < OTHER_MAX_CANVAS_DIMENSION &&
437
- targetHeight > MAX_CANVAS_DIMENSION
438
- ) {
439
- scaleHeight = scaleWidth = MAX_CANVAS_DIMENSION / targetHeight
440
- }
410
+ const safetyMargin = toImageOptions.safetyMargin || 0 // 额外的安全边距
411
+
412
+ let targetWidth = bboxWidth * dpr
413
+ let targetHeight = bboxHeight * dpr
441
414
 
442
- if (scaleWidth < 1 || scaleHeight < 1) {
443
- targetWidth = Math.floor(targetWidth * scaleWidth)
444
- targetHeight = Math.floor(targetHeight * scaleHeight)
415
+ // 超出 canvas 大小限制时,进行等比缩放
416
+ const scaleRatio = this.getCanvasScaleRatio(targetWidth, targetHeight)
417
+ if (scaleRatio < 1) {
418
+ targetWidth = Math.floor(targetWidth * scaleRatio)
419
+ targetHeight = Math.floor(targetHeight * scaleRatio)
445
420
  }
421
+
446
422
  // 将导出区域移动到左上角,canvas 绘制的时候是从左上角开始绘制的
447
423
  // 在transform矩阵中加入padding值,确保左侧元素不会被截断
448
424
  // 对这个矩阵进行缩放,否则会导致截断
449
425
  ;(copy.lastChild as SVGElement).style.transform =
450
- `matrix(${scaleWidth}, 0, 0, ${scaleHeight}, ${
451
- (-offsetX + TRANSLATE_X) * (1 / SCALE_X) * scaleWidth + padding / dpr
452
- }, ${
453
- (-offsetY + TRANSLATE_Y) * (1 / SCALE_Y) * scaleHeight + padding / dpr
454
- })`
455
- canvas.width = targetWidth
456
- canvas.height = targetHeight
426
+ `matrix(${scaleRatio}, 0, 0, ${scaleRatio}, ${
427
+ (-offsetX + TRANSLATE_X) * (1 / SCALE_X) * scaleRatio +
428
+ padding +
429
+ factorWidth / 2 +
430
+ safetyMargin
431
+ }, ${(-offsetY + TRANSLATE_Y) * (1 / SCALE_Y) * scaleRatio + padding + factorHeight / 2 + safetyMargin})`
432
+ canvas.width = targetWidth + (padding + safetyMargin) * 2 * dpr
433
+ canvas.height = targetHeight + (padding + safetyMargin) * 2 * dpr
457
434
  const ctx = canvas.getContext('2d')
458
435
  if (ctx) {
459
436
  // 清空canvas
460
437
  ctx.clearRect(0, 0, canvas.width, canvas.height)
461
- ctx.scale(dpr * scaleWidth, dpr * scaleHeight)
438
+ ctx.scale(dpr, dpr)
462
439
  // 如果有背景色,设置流程图导出的背景色
463
440
  if (backgroundColor) {
464
441
  ctx.fillStyle = backgroundColor
@@ -690,12 +667,6 @@ export class Snapshot {
690
667
  fileType?: string,
691
668
  toImageOptions?: ToImageOptions,
692
669
  ): Promise<SnapshotResponse> {
693
- console.log(
694
- 'getSnapshotBase64---------------',
695
- backgroundColor,
696
- fileType,
697
- toImageOptions,
698
- )
699
670
  return await this.withExportPreparation(
700
671
  () => this._getSnapshotBase64(backgroundColor, fileType, toImageOptions),
701
672
  toImageOptions,