From 6d729c53ab882d6c761207b3a76b559a50c91f83 Mon Sep 17 00:00:00 2001 From: wanglin2 <1013335014@qq.com> Date: Sun, 6 Apr 2025 17:09:36 +0800 Subject: [PATCH] =?UTF-8?q?Feat:=E5=AF=BC=E5=87=BA=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E5=92=8Cpdf=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AE=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E6=98=BE=E7=A4=BA=E5=AE=8C=E6=95=B4=E8=83=8C=E6=99=AF?= =?UTF-8?q?=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- simple-mind-map/src/plugins/Export.js | 51 +++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/simple-mind-map/src/plugins/Export.js b/simple-mind-map/src/plugins/Export.js index f1e32456..15075c23 100644 --- a/simple-mind-map/src/plugins/Export.js +++ b/simple-mind-map/src/plugins/Export.js @@ -128,7 +128,7 @@ class Export { } // svg转png - svgToPng(svgSrc, transparent, clipData = null) { + svgToPng(svgSrc, transparent, clipData = null, fitBg = false) { const { maxCanvasSize, minExportImgCanvasScale } = this.mindMap.opt return new Promise((resolve, reject) => { const img = new Image() @@ -149,10 +149,37 @@ class Export { imgWidth = clipData.width + paddingX * 2 imgHeight = clipData.height + paddingY * 2 } + // 适配背景图片的大小 + let fitBgImgWidth = 0 + let fitBgImgHeight = 0 + const { backgroundImage } = this.mindMap.themeConfig + if (fitBg && backgroundImage && !transparent) { + const bgImgSize = await new Promise(resolve => { + const bgImg = new Image() + bgImg.onload = () => { + resolve([bgImg.width, bgImg.height]) + } + bgImg.onerror = () => { + resolve(null) + } + bgImg.src = backgroundImage + }) + if (bgImgSize) { + const imgRatio = imgWidth / imgHeight + const bgRatio = bgImgSize[0] / bgImgSize[1] + if (imgRatio > bgRatio) { + fitBgImgWidth = imgWidth + fitBgImgHeight = imgWidth / bgRatio + } else { + fitBgImgHeight = imgHeight + fitBgImgWidth = imgHeight * bgRatio + } + } + } // 检查是否超出canvas支持的像素上限 // canvas大小需要乘以dpr - let canvasWidth = imgWidth * dpr - let canvasHeight = imgHeight * dpr + let canvasWidth = (fitBgImgWidth || imgWidth) * dpr + let canvasHeight = (fitBgImgHeight || imgHeight) * dpr if (canvasWidth > maxCanvasSize || canvasHeight > maxCanvasSize) { let newWidth = null let newHeight = null @@ -187,6 +214,10 @@ class Export { } // 图片绘制到canvas里 // 如果有裁减数据,那么需要进行裁减 + const fitBgLeft = + fitBgImgWidth > 0 ? (fitBgImgWidth - imgWidth) / 2 : 0 + const fitBgTop = + fitBgImgHeight > 0 ? (fitBgImgHeight - imgHeight) / 2 : 0 if (clipData) { ctx.drawImage( img, @@ -194,13 +225,13 @@ class Export { clipData.top, clipData.width, clipData.height, - paddingX, - paddingY, + paddingX + fitBgLeft, + paddingY + fitBgTop, clipData.width, clipData.height ) } else { - ctx.drawImage(img, 0, 0, styleWidth, styleHeight) + ctx.drawImage(img, fitBgLeft, fitBgTop, imgWidth, imgHeight) } resolve(canvas.toDataURL()) } catch (error) { @@ -285,12 +316,12 @@ class Export { * 方法1.把svg的图片都转化成data:url格式,再转换 * 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换 */ - async png(name, transparent = false, node = null) { + async png(name, transparent = false, node = null, fitBg = false) { this.mindMap.renderer.textEdit.hideEditTextBox() this.handleNodeExport(node) const { str, clipData } = await this.getSvgData(node) const svgUrl = await this.fixSvgStrAndToBlob(str) - const res = await this.svgToPng(svgUrl, transparent, clipData) + const res = await this.svgToPng(svgUrl, transparent, clipData, fitBg) return res } @@ -306,11 +337,11 @@ class Export { } // 导出为pdf - async pdf(name, transparent = false) { + async pdf(name, transparent = false, fitBg = false) { if (!this.mindMap.doExportPDF) { throw new Error('请注册ExportPDF插件') } - const img = await this.png(name, transparent) + const img = await this.png(name, transparent, null, fitBg) // 使用jspdf库 // await this.mindMap.doExportPDF.pdf(name, img) // 使用pdf-lib库