From 9f9ed1e84f4711db377ac024550bcc779e40279f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A1=97=E8=A7=92=E5=B0=8F=E6=9E=97?= <1013335014@qq.com> Date: Thu, 19 Sep 2024 19:36:10 +0800 Subject: [PATCH] =?UTF-8?q?Fix=EF=BC=9A=E4=BF=AE=E5=A4=8D=E6=80=9D?= =?UTF-8?q?=E7=BB=B4=E5=AF=BC=E5=9B=BE=E9=9D=9E=E5=B8=B8=E5=A4=A7=E7=9A=84?= =?UTF-8?q?=E6=83=85=E5=86=B5=E4=B8=8B=E5=AF=BC=E5=87=BA=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/constants/defaultOptions.js | 2 + simple-mind-map/src/plugins/Export.js | 49 +++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/simple-mind-map/src/constants/defaultOptions.js b/simple-mind-map/src/constants/defaultOptions.js index f6ed199b..b037710b 100644 --- a/simple-mind-map/src/constants/defaultOptions.js +++ b/simple-mind-map/src/constants/defaultOptions.js @@ -318,6 +318,8 @@ export const defaultOpt = { // 导出png、svg、pdf时会获取画布上的svg数据进行克隆,然后通过该克隆的元素进行导出,如果你想对该克隆元素做一些处理,比如新增、替换、修改其中的一些元素,那么可以通过该参数传递一个处理函数,接收svg元素对象,处理后,需要返回原svg元素对象。 // 需要注意的是svg对象指的是@svgdotjs/svg.js库的元素对象,所以你需要阅读该库的文档来操作该对象 handleBeingExportSvg: null, + // 导出图片或pdf都是通过canvas将svg绘制出来,再导出,所以如果思维导图特别大,宽高可能会超出canvas支持的上限,所以会进行缩放,这个上限可以通过该参数设置,代表canvas宽和高的最大宽度 + maxCanvasSize: 16384, // 【AssociativeLine插件】 // 关联线默认文字 diff --git a/simple-mind-map/src/plugins/Export.js b/simple-mind-map/src/plugins/Export.js index 52413970..bb57645b 100644 --- a/simple-mind-map/src/plugins/Export.js +++ b/simple-mind-map/src/plugins/Export.js @@ -129,6 +129,7 @@ class Export { // svg转png svgToPng(svgSrc, transparent, clipData = null) { + const { maxCanvasSize, minExportImgCanvasScale } = this.mindMap.opt return new Promise((resolve, reject) => { const img = new Image() // 跨域图片需要添加这个属性,否则画布被污染了无法导出图片 @@ -136,10 +137,7 @@ class Export { img.onload = async () => { try { const canvas = document.createElement('canvas') - const dpr = Math.max( - window.devicePixelRatio, - this.mindMap.opt.minExportImgCanvasScale - ) + const dpr = Math.max(window.devicePixelRatio, minExportImgCanvasScale) let imgWidth = img.width let imgHeight = img.height // 如果是裁减操作的话,那么需要手动添加内边距,及调整图片大小为实际的裁减区域的大小,不要忘了内边距哦 @@ -152,29 +150,40 @@ class Export { imgHeight = clipData.height + paddingY * 2 } // 检查是否超出canvas支持的像素上限 - const maxSize = 16384 / dpr - const maxArea = maxSize * maxSize - if (imgWidth * imgHeight > maxArea) { + // canvas大小需要乘以dpr + let canvasWidth = imgWidth * dpr + let canvasHeight = imgHeight * dpr + if (canvasWidth > maxCanvasSize || canvasHeight > maxCanvasSize) { let newWidth = null let newHeight = null - if (imgWidth > maxSize) { - newWidth = maxArea / imgHeight - } else if (imgHeight > maxSize) { - newHeight = maxArea / imgWidth + if (canvasWidth > maxCanvasSize) { + // 如果宽度超出限制,那么调整为上限值 + newWidth = maxCanvasSize + } else if (canvasHeight > maxCanvasSize) { + // 高度同理 + newHeight = maxCanvasSize } - const res = resizeImgSize(imgWidth, imgHeight, newWidth, newHeight) - imgWidth = res[0] - imgHeight = res[1] + // 计算缩放后的宽高 + const res = resizeImgSize( + canvasWidth, + canvasHeight, + newWidth, + newHeight + ) + canvasWidth = res[0] + canvasHeight = res[1] } - canvas.width = imgWidth * dpr - canvas.height = imgHeight * dpr - canvas.style.width = imgWidth + 'px' - canvas.style.height = imgHeight + 'px' + canvas.width = canvasWidth + canvas.height = canvasHeight + const styleWidth = canvasWidth / dpr + const styleHeight = canvasHeight / dpr + canvas.style.width = styleWidth + 'px' + canvas.style.height = styleHeight + 'px' const ctx = canvas.getContext('2d') ctx.scale(dpr, dpr) // 绘制背景 if (!transparent) { - await this.drawBackgroundToCanvas(ctx, imgWidth, imgHeight) + await this.drawBackgroundToCanvas(ctx, styleWidth, styleHeight) } // 图片绘制到canvas里 // 如果有裁减数据,那么需要进行裁减 @@ -191,7 +200,7 @@ class Export { clipData.height ) } else { - ctx.drawImage(img, 0, 0, imgWidth, imgHeight) + ctx.drawImage(img, 0, 0, styleWidth, styleHeight) } resolve(canvas.toDataURL()) } catch (error) {