From 222e25a36967a5fcd5553c1994ad9e7f9a43bc47 Mon Sep 17 00:00:00 2001 From: lyc Date: Fri, 19 Jul 2024 17:19:46 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=8E=8B=E7=BC=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Export.js | 101 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 5 deletions(-) diff --git a/src/Export.js b/src/Export.js index 80be69e..5b7afd8 100644 --- a/src/Export.js +++ b/src/Export.js @@ -50,13 +50,14 @@ export default class Export { } // 导出为图片 - exportImage({ + async exportImage({ type = 'image/png', renderBg = true, useBlob = false, paddingX = 10, paddingY = 10, - onlySelected + onlySelected, + backgroundColor } = {}) { // 计算所有元素的外包围框 let { minx, maxx, miny, maxy } = getMultiElementRectInfo( @@ -64,6 +65,11 @@ export default class Export { ) let width = maxx - minx + paddingX * 2 let height = maxy - miny + paddingY * 2 + if(!width && !height){ + width = this.app.width + height = this.app.height + backgroundColor = '#ffffff' + } // 创建导出canvas let { canvas, ctx } = createCanvas(width, height, { noStyle: true, @@ -73,12 +79,12 @@ export default class Export { this.saveAppState() this.changeAppState(minx - paddingX, miny - paddingY, ctx) // 绘制背景颜色 - if (renderBg && this.app.state.backgroundColor) { + if (renderBg && backgroundColor ? backgroundColor : this.app.state.backgroundColor) { this.app.background.canvasAddBackgroundColor( ctx, width, height, - this.app.state.backgroundColor + backgroundColor ) } // 绘制元素到导出canvas @@ -96,9 +102,94 @@ export default class Export { }, type) }) } else { - return canvas.toDataURL(type, 0.9) + + return await this.compressImg(canvas.toDataURL(type), 1, 0.2,type) + } } + /** + * 压缩base64图片的函数 + * + * @param {string} base64 - 图片的base64编码 + * @param {number} multiple - 缩放比例 + * @param {number} quality - 输出图片的质量(0.0到1.0之间) + * @param {string} format - 输出图片的格式,默认为"image/webp" 可选参数 image/png、image/jpeg、image/webp 等 + * @param {number} min - 压缩后图片的最小KB大小 + * @param {number} max - 压缩后图片的最大KB大小 + * @returns {Promise} - 返回压缩后的图片的base64编码 + */ + + + compressImg(base64, multiple, quality, format = "image/webp", min, max) { + return new Promise((resolve, reject) => { + try { + // 如果base64为空,则直接返回 + if (!base64) { + return; + } + // 创建一个新的Image对象 + let newImage = new Image(); + // 设置Image对象的src为传入的base64编码 + newImage.src = base64; + // 设置crossOrigin属性为'Anonymous',用于处理跨域图片 + newImage.setAttribute('crossOrigin', 'Anonymous'); + + // 定义图片的宽度、高度和缩放比例 + let imgWidth, imgHeight, proportion; + + // 当图片加载完成后执行的操作 + newImage.onload = function() { + // 计算缩放后的宽度 + proportion = this.width * multiple; + // 记录原始宽度和高度 + imgWidth = this.width; + imgHeight = this.height; + + // 创建一个canvas元素 + let canvas = document.createElement('canvas'); + // 获取canvas的2D渲染上下文 + let ctx = canvas.getContext('2d'); + + // 设置canvas的宽高,按照等比例缩放 + // 等比例缩小放大 + canvas.width = proportion; + canvas.height = proportion * (imgHeight / imgWidth); + + // 清除canvas上的内容 + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // 在canvas上绘制缩放后的图片 + ctx.drawImage(this, 0, 0, canvas.width, canvas.height); + + // 将canvas转换为base64编码的图片 + let smallBase64 = canvas.toDataURL(format, quality); + + // 如果设置了最小KB大小,并且压缩后的图片大小小于最小KB大小,则增加质量并重新压缩 + if (min && smallBase64.length / 1024 < min) { + while (smallBase64.length / 1024 < min) { + quality += 0.01; + smallBase64 = canvas.toDataURL(format, quality); + } + } + // 如果设置了最大KB大小,并且压缩后的图片大小大于最大KB大小,则减小质量并重新压缩 + else if (max && smallBase64.length / 1024 > max) { + while (smallBase64.length / 1024 > max) { + quality -= 0.01; + smallBase64 = canvas.toDataURL(format, quality); + } + } + + // 将压缩后的图片的base64编码作为Promise的解决值返回 + resolve(smallBase64); + }; + } catch (error) { + reject(error) + throw new Error(error); + } + }); + } + + // 保存app类当前状态数据 saveAppState() {