diff --git a/simple-mind-map/src/constants/constant.js b/simple-mind-map/src/constants/constant.js index a4e8abf58..34778c383 100644 --- a/simple-mind-map/src/constants/constant.js +++ b/simple-mind-map/src/constants/constant.js @@ -332,12 +332,6 @@ export const ERROR_TYPES = { EXPORT_LOAD_IMAGE_ERROR: 'export_load_image_error' } -// a4纸的宽高 -export const a4Size = { - width: 592.28, - height: 841.89 -} - // css export const cssContent = ` /* 鼠标hover和激活时渲染的矩形 */ diff --git a/simple-mind-map/src/plugins/Export.js b/simple-mind-map/src/plugins/Export.js index 31d2d3bc3..b49e46f5f 100644 --- a/simple-mind-map/src/plugins/Export.js +++ b/simple-mind-map/src/plugins/Export.js @@ -9,7 +9,7 @@ import { import { SVG } from '@svgdotjs/svg.js' import drawBackgroundImageToCanvas from '../utils/simulateCSSBackgroundInCanvas' import { transformToMarkdown } from '../parse/toMarkdown' -import { a4Size, ERROR_TYPES } from '../constants/constant' +import { ERROR_TYPES } from '../constants/constant' // 导出插件 class Export { @@ -92,14 +92,7 @@ class Export { } // svg转png - svgToPng( - svgSrc, - transparent, - checkRotate = () => { - return false - }, - compress - ) { + svgToPng(svgSrc, transparent, ignoreDpr = false) { return new Promise((resolve, reject) => { const img = new Image() // 跨域图片需要添加这个属性,否则画布被污染了无法导出图片 @@ -107,42 +100,20 @@ class Export { img.onload = async () => { try { const canvas = document.createElement('canvas') - const dpr = Math.max( - window.devicePixelRatio, - this.mindMap.opt.minExportImgCanvasScale - ) + const dpr = ignoreDpr + ? 1 + : Math.max( + window.devicePixelRatio, + this.mindMap.opt.minExportImgCanvasScale + ) let imgWidth = img.width let imgHeight = img.height - // 压缩图片 - if (compress) { - const compressedSize = resizeImgSize( - imgWidth, - imgHeight, - compress.width, - compress.height - ) - imgWidth = compressedSize[0] - imgHeight = compressedSize[1] - } - // 如果宽比高长,那么旋转90度 - const needRotate = checkRotate(imgWidth, imgHeight) - if (needRotate) { - canvas.width = imgHeight * dpr - canvas.height = imgWidth * dpr - canvas.style.width = imgHeight + 'px' - canvas.style.height = imgWidth + 'px' - } else { - canvas.width = imgWidth * dpr - canvas.height = imgHeight * dpr - canvas.style.width = imgWidth + 'px' - canvas.style.height = imgHeight + 'px' - } + canvas.width = imgWidth * dpr + canvas.height = imgHeight * dpr + canvas.style.width = imgWidth + 'px' + canvas.style.height = imgHeight + 'px' const ctx = canvas.getContext('2d') ctx.scale(dpr, dpr) - if (needRotate) { - ctx.rotate(0.5 * Math.PI) - ctx.translate(0, -imgHeight) - } // 绘制背景 if (!transparent) { await this.drawBackgroundToCanvas(ctx, imgWidth, imgHeight) @@ -232,31 +203,22 @@ class Export { * 方法1.把svg的图片都转化成data:url格式,再转换 * 方法2.把svg的图片提取出来再挨个绘制到canvas里,最后一起转换 */ - async png(name, transparent = false, checkRotate, compress) { + async png(name, transparent = false) { const { str } = await this.getSvgData() const svgUrl = await this.fixSvgStrAndToBlob(str) - // 绘制到canvas上 - const res = await this.svgToPng(svgUrl, transparent, checkRotate, compress) + const res = await this.svgToPng(svgUrl, transparent) return res } // 导出为pdf - async pdf(name, useMultiPageExport, maxImageWidth) { + async pdf(name, transparent = false) { if (!this.mindMap.doExportPDF) { throw new Error('请注册ExportPDF插件') } - const img = await this.png( - '', - false, - (width, height) => { - if (width <= a4Size.width && height && a4Size.height) return false - return width / height > 1 - }, - { - width: maxImageWidth || a4Size.width * 2 - } - ) - await this.mindMap.doExportPDF.pdf(name, img, useMultiPageExport) + const { str } = await this.getSvgData() + const svgUrl = await this.fixSvgStrAndToBlob(str) + const img = await this.svgToPng(svgUrl, transparent, true) + await this.mindMap.doExportPDF.pdf(name, img) } // 导出为xmind diff --git a/simple-mind-map/src/plugins/ExportPDF.js b/simple-mind-map/src/plugins/ExportPDF.js index 801193f69..6d231e9ac 100644 --- a/simple-mind-map/src/plugins/ExportPDF.js +++ b/simple-mind-map/src/plugins/ExportPDF.js @@ -1,5 +1,4 @@ import JsPDF from '../utils/jspdf' -import { a4Size } from '../constants/constant' // 导出PDF插件,需要通过Export插件使用 class ExportPDF { @@ -9,104 +8,20 @@ class ExportPDF { } // 导出为pdf - async pdf(name, img, useMultiPageExport = false) { - if (useMultiPageExport) { - await this.multiPageExport(name, img) - } else { - await this.onePageExport(name, img) - } - } - - // 单页导出 - onePageExport(name, img) { - return new Promise((resolve, reject) => { - let pdf = new JsPDF({ - unit: 'pt', - format: 'a4', - compress: true - }) - let a4Ratio = a4Size.width / a4Size.height - let image = new Image() - image.onload = () => { - let imageWidth = image.width - let imageHeight = image.height - let imageRatio = imageWidth / imageHeight - let w, h - if (imageWidth <= a4Size.width && imageHeight <= a4Size.height) { - // 使用图片原始宽高 - w = imageWidth - h = imageHeight - } else if (a4Ratio > imageRatio) { - // 以a4Height为高度,缩放图片宽度 - w = imageRatio * a4Size.height - h = a4Size.height - } else { - // 以a4Width为宽度,缩放图片高度 - w = a4Size.width - h = a4Size.width / imageRatio - } - pdf.addImage( - img, - 'PNG', - (a4Size.width - w) / 2, - (a4Size.height - h) / 2, - w, - h - ) - pdf.save(name) - resolve() - } - image.onerror = e => { - reject(e) - } - image.src = img - }) - } - - // 多页导出 - multiPageExport(name, img) { + async pdf(name, img) { return new Promise((resolve, reject) => { - let image = new Image() + const image = new Image() image.onload = () => { - let imageWidth = image.width - let imageHeight = image.height - // 一页pdf显示高度 - let pageHeight = (imageWidth / a4Size.width) * a4Size.height - // 未生成pdf的高度 - let leftHeight = imageHeight - // 偏移 - let position = 0 - // a4纸的尺寸[595.28,841.89],图片在pdf中图片的宽高 - let imgWidth = a4Size.width - let imgHeight = (a4Size.width / imageWidth) * imageHeight - let pdf = new JsPDF({ - unit: 'pt', - format: 'a4', - compress: true + const imageWidth = image.width + const imageHeight = image.height + const pdf = new JsPDF({ + unit: 'px', + format: [imageWidth, imageHeight], + compress: true, + hotfixes: ['px_scaling'], + orientation: imageWidth > imageHeight ? 'landscape' : 'portrait' }) - // 有两个高度需要区分,一个是图片的实际高度,和生成pdf的页面高度(841.89) - // 当内容未超过pdf一页显示的范围,无需分页 - if (leftHeight < pageHeight) { - pdf.addImage( - img, - 'PNG', - (a4Size.width - imgWidth) / 2, - (a4Size.height - imgHeight) / 2, - imgWidth, - imgHeight - ) - } else { - // 分页 - while (leftHeight > 0) { - pdf.addImage(img, 'PNG', 0, position, imgWidth, imgHeight) - leftHeight -= pageHeight - position -= a4Size.height - // 避免添加空白页 - if (leftHeight > 0) { - pdf.addPage() - } - } - } + pdf.addImage(img, 'PNG', 0, 0, imageWidth, imageHeight) pdf.save(name) resolve() } diff --git a/web/src/pages/Edit/components/Export.vue b/web/src/pages/Edit/components/Export.vue index 4e99ab8d7..9b114eab5 100644 --- a/web/src/pages/Edit/components/Export.vue +++ b/web/src/pages/Edit/components/Export.vue @@ -48,17 +48,11 @@ @keydown.native.stop > {{ $t('export.isTransparent') }} - {{ $t('export.useMultiPageExport') }}