Feat:导出图片和pdf支持设置是否显示完整背景图片

This commit is contained in:
wanglin2 2025-04-06 17:09:36 +08:00
parent 08df73aec4
commit 6d729c53ab

View File

@ -128,7 +128,7 @@ class Export {
} }
// svg转png // svg转png
svgToPng(svgSrc, transparent, clipData = null) { svgToPng(svgSrc, transparent, clipData = null, fitBg = false) {
const { maxCanvasSize, minExportImgCanvasScale } = this.mindMap.opt const { maxCanvasSize, minExportImgCanvasScale } = this.mindMap.opt
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const img = new Image() const img = new Image()
@ -149,10 +149,37 @@ class Export {
imgWidth = clipData.width + paddingX * 2 imgWidth = clipData.width + paddingX * 2
imgHeight = clipData.height + paddingY * 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支持的像素上限
// canvas大小需要乘以dpr // canvas大小需要乘以dpr
let canvasWidth = imgWidth * dpr let canvasWidth = (fitBgImgWidth || imgWidth) * dpr
let canvasHeight = imgHeight * dpr let canvasHeight = (fitBgImgHeight || imgHeight) * dpr
if (canvasWidth > maxCanvasSize || canvasHeight > maxCanvasSize) { if (canvasWidth > maxCanvasSize || canvasHeight > maxCanvasSize) {
let newWidth = null let newWidth = null
let newHeight = null let newHeight = null
@ -187,6 +214,10 @@ class Export {
} }
// 图片绘制到canvas里 // 图片绘制到canvas里
// 如果有裁减数据,那么需要进行裁减 // 如果有裁减数据,那么需要进行裁减
const fitBgLeft =
fitBgImgWidth > 0 ? (fitBgImgWidth - imgWidth) / 2 : 0
const fitBgTop =
fitBgImgHeight > 0 ? (fitBgImgHeight - imgHeight) / 2 : 0
if (clipData) { if (clipData) {
ctx.drawImage( ctx.drawImage(
img, img,
@ -194,13 +225,13 @@ class Export {
clipData.top, clipData.top,
clipData.width, clipData.width,
clipData.height, clipData.height,
paddingX, paddingX + fitBgLeft,
paddingY, paddingY + fitBgTop,
clipData.width, clipData.width,
clipData.height clipData.height
) )
} else { } else {
ctx.drawImage(img, 0, 0, styleWidth, styleHeight) ctx.drawImage(img, fitBgLeft, fitBgTop, imgWidth, imgHeight)
} }
resolve(canvas.toDataURL()) resolve(canvas.toDataURL())
} catch (error) { } catch (error) {
@ -285,12 +316,12 @@ class Export {
* 方法1.把svg的图片都转化成data:url格式再转换 * 方法1.把svg的图片都转化成data:url格式再转换
* 方法2.把svg的图片提取出来再挨个绘制到canvas里最后一起转换 * 方法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.mindMap.renderer.textEdit.hideEditTextBox()
this.handleNodeExport(node) this.handleNodeExport(node)
const { str, clipData } = await this.getSvgData(node) const { str, clipData } = await this.getSvgData(node)
const svgUrl = await this.fixSvgStrAndToBlob(str) 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 return res
} }
@ -306,11 +337,11 @@ class Export {
} }
// 导出为pdf // 导出为pdf
async pdf(name, transparent = false) { async pdf(name, transparent = false, fitBg = false) {
if (!this.mindMap.doExportPDF) { if (!this.mindMap.doExportPDF) {
throw new Error('请注册ExportPDF插件') throw new Error('请注册ExportPDF插件')
} }
const img = await this.png(name, transparent) const img = await this.png(name, transparent, null, fitBg)
// 使用jspdf库 // 使用jspdf库
// await this.mindMap.doExportPDF.pdf(name, img) // await this.mindMap.doExportPDF.pdf(name, img)
// 使用pdf-lib库 // 使用pdf-lib库