Files
font2pic/miniprogram/utils/mp/canvas-export.js
2026-02-08 18:28:39 +08:00

132 lines
3.1 KiB
JavaScript

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 needAuth = errMsg.includes('auth deny') || errMsg.includes('authorize')
if (needAuth) {
const modalRes = await showModal({
title: '需要相册权限',
content: '请在设置中开启“保存到相册”权限后重试。',
confirmText: '去设置',
})
if (modalRes.confirm) {
await openSetting()
}
}
return {
success: false,
needAuth,
error,
}
}
}
module.exports = {
exportSvgToPngByCanvas,
savePngToAlbum,
}