From 107ebd7a1da4f6d5369f2d2950b83d7dd3964b29 Mon Sep 17 00:00:00 2001 From: chenhao Date: Tue, 26 May 2026 21:25:23 +0800 Subject: [PATCH] html!!!save --- src/utils/html2image.js | 121 +++++++++++++++++++++------------ src/views/Merchant/PayCode.vue | 51 +++++--------- src/views/User/Invite.vue | 4 +- 3 files changed, 96 insertions(+), 80 deletions(-) diff --git a/src/utils/html2image.js b/src/utils/html2image.js index 7ab15f5..ae8e402 100644 --- a/src/utils/html2image.js +++ b/src/utils/html2image.js @@ -1,74 +1,107 @@ /** * HTML转图片工具 - * 基于 html2canvas 实现,兼容低版本 Safari/微信 + * 基于 html-to-image 将DOM元素转换为图片 */ -import html2canvas from 'html2canvas'; +import { toCanvas } from 'html-to-image' /** * 将DOM元素转换为图片 * @param {string|HTMLElement} selector - DOM选择器或元素 * @param {Object} options - 配置选项 + * @param {number} [options.width] - 自定义宽度(会应用到元素上) + * @param {number} [options.height] - 自定义高度(会应用到元素上) + * @param {number} [options.canvasWidth] - 输出画布宽度 + * @param {number} [options.canvasHeight] - 输出画布高度 * @param {number} [options.pixelRatio] - 像素比例,默认2 + * @param {boolean} [options.useCORS] - 是否允许跨域,默认true * @param {string} [options.format] - 图片格式,'png'或'jpeg',默认'png' * @param {number} [options.quality] - 图片质量,0-1,仅jpeg有效,默认1.0 * @returns {Promise} - 返回base64图片数据URL */ export async function toDataURL(selector, options = {}) { - const { - pixelRatio = 2, - format = 'png', - quality = 1.0 - } = options; + const { + width, + height, + canvasWidth, + canvasHeight, + pixelRatio = 2, + useCORS = true, + format = 'png', + quality = 1.0 + } = options - const element = typeof selector === 'string' ? document.querySelector(selector) : selector; - if (!element) throw new Error('Element not found'); + const element = typeof selector === 'string' ? document.querySelector(selector) : selector + if (!element) { + throw new Error('Element not found') + } - const canvas = await html2canvas(element, { - scale: pixelRatio, - useCORS: true, - allowTaint: false, - backgroundColor: '#ffffff', - dpi: window.devicePixelRatio * pixelRatio, - logging: false - }); + const canvasEl = await toCanvas(element, { + width, + height, + canvasWidth, + canvasHeight, + pixelRatio, + cors: useCORS, + backgroundColor: '#ffffff' + }) - const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png'; - return canvas.toDataURL(mimeType, quality); + const mimeType = format === 'jpeg' ? 'image/jpeg' : 'image/png' + return canvasEl.toDataURL(mimeType, quality) } /** * 将DOM元素转换为图片并下载 + * @param {string|HTMLElement} selector - DOM选择器或元素 + * @param {string} [filename] - 下载文件名,不含扩展名 + * @param {Object} options - 配置选项,同toDataURL */ export async function toImageDownload(selector, filename = 'download', options = {}) { - const dataUrl = await toDataURL(selector, options); - const link = document.createElement('a'); - link.download = filename + '.png'; - link.href = dataUrl; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); + const dataUrl = await toDataURL(selector, options) + + const link = document.createElement('a') + link.download = filename + '.png' + link.href = dataUrl + document.body.appendChild(link) + link.click() + document.body.removeChild(link) } /** - * 转为 Blob + * 将DOM元素转换为Blob + * @param {string|HTMLElement} selector - DOM选择器或元素 + * @param {Object} options - 配置选项,同toDataURL + * @returns {Promise} */ -export function toBlob(selector, options = {}) { - return new Promise(async (resolve, reject) => { - try { - const dataUrl = await toDataURL(selector, options); - const arr = dataUrl.split(','); - const mime = arr[0].match(/:(.*?);/)[1]; - const bstr = atob(arr[1]); - const u8arr = new Uint8Array(bstr.length); - for (let i = 0; i < bstr.length; i++) { - u8arr[i] = bstr.charCodeAt(i); - } - resolve(new Blob([u8arr], { type: mime })); - } catch (e) { - reject(e); - } - }); +export async function toBlob(selector, options = {}) { + const dataUrl = await toDataURL(selector, options) + + const arr = dataUrl.split(',') + const mime = arr[0].match(/:(.*?);/)[1] + const bstr = atob(arr[1]) + let n = bstr.length + const u8arr = new Uint8Array(n) + while (n--) { + u8arr[n] = bstr.charCodeAt(n) + } + return new Blob([u8arr], { type: mime }) } -export default { toDataURL, toImageDownload, toBlob }; \ No newline at end of file +/** + * 通过 dataURL 直接下载图片 + */ +export function downloadByDataURL(dataUrl, filename = 'download') { + const link = document.createElement('a') + link.download = filename + '.png' + link.href = dataUrl + document.body.appendChild(link) + link.click() + document.body.removeChild(link) +} + +export default { + toDataURL, + toImageDownload, + toBlob, + downloadByDataURL +} \ No newline at end of file diff --git a/src/views/Merchant/PayCode.vue b/src/views/Merchant/PayCode.vue index cd2e491..4d4902b 100644 --- a/src/views/Merchant/PayCode.vue +++ b/src/views/Merchant/PayCode.vue @@ -11,7 +11,7 @@