const { canvasToTempFilePath, saveImageToPhotosAlbum, writeFile, openSetting, showModal, } = require('./wx-promisify') function getWindowDpr() { if (typeof wx.getWindowInfo === 'function') { return wx.getWindowInfo().pixelRatio || 1 } const info = wx.getSystemInfoSync() return info.pixelRatio || 1 } function queryCanvasNode(page, selector) { return new Promise((resolve, reject) => { const query = wx.createSelectorQuery().in(page) query .select(selector) .fields({ node: true, size: true }) .exec((result) => { const target = result && result[0] if (!target || !target.node) { reject(new Error('未找到导出画布节点')) return } resolve(target) }) }) } async function writeSvgTempFile(svgString) { const path = `${wx.env.USER_DATA_PATH}/font2svg_preview_${Date.now()}.svg` await writeFile(path, svgString, 'utf8') return path } async function exportSvgToPngByCanvas(page, options) { const { svgString, width, height, selector = '#exportCanvas', backgroundColor = '#ffffff', } = options if (!svgString) { throw new Error('缺少 SVG 内容') } const canvasNode = await queryCanvasNode(page, selector) const canvas = canvasNode.node const ctx = canvas.getContext('2d') const dpr = getWindowDpr() const renderWidth = Math.max(1, Math.min(2048, Math.round(width || canvasNode.width || 1024))) const renderHeight = Math.max(1, Math.min(2048, Math.round(height || canvasNode.height || 1024))) canvas.width = renderWidth * dpr canvas.height = renderHeight * dpr if (typeof ctx.setTransform === 'function') { ctx.setTransform(dpr, 0, 0, dpr, 0, 0) } else { ctx.scale(dpr, dpr) } ctx.fillStyle = backgroundColor ctx.fillRect(0, 0, renderWidth, renderHeight) const svgPath = await writeSvgTempFile(svgString) const image = canvas.createImage() await new Promise((resolve, reject) => { image.onload = resolve image.onerror = () => reject(new Error('加载 SVG 到画布失败')) image.src = svgPath }) ctx.drawImage(image, 0, 0, renderWidth, renderHeight) const fileRes = await canvasToTempFilePath( { canvas, x: 0, y: 0, width: renderWidth, height: renderHeight, destWidth: renderWidth, destHeight: renderHeight, fileType: 'png', }, page ) return fileRes.tempFilePath } async function savePngToAlbum(filePath) { try { await saveImageToPhotosAlbum(filePath) return { success: true } } catch (error) { const errMsg = String(error && error.errMsg ? error.errMsg : error) const lowerErrMsg = errMsg.toLowerCase() const needAuth = lowerErrMsg.includes('auth deny') || lowerErrMsg.includes('authorize') const privateApiBanned = lowerErrMsg.includes('private api banned') if (needAuth) { const modalRes = await showModal({ title: '需要相册权限', content: '请在设置中开启“保存到相册”权限后重试。', confirmText: '去设置', }) if (modalRes.confirm) { await openSetting() } } return { success: false, needAuth, privateApiBanned, reason: privateApiBanned ? 'private_api_banned' : (needAuth ? 'auth_denied' : 'save_failed'), error, } } } module.exports = { exportSvgToPngByCanvas, savePngToAlbum, }