132 lines
3.1 KiB
JavaScript
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,
|
|
}
|