說明
- canvas 舊版本生成圖片沒有長度限制
- canvas 新版本(2d)生成圖片有長度限制:4096
工具: CanvasUtil.js
import { debug } from '../../../../utils/log'
class CanvasUtil {
constructor(that, { canvasId, w, h }) {
this.that = thatthis.w = w
this.h = h
this.canvasId = canvasId
this.ctx = wx.createCanvasContext(canvasId, that)this.init()
}init() {
// 清空畫布
this.ctx.clearRect(0, 0, this.w, this.h)
}// 文本長度
textWidth({ text, size, color, weight }) {
this.ctx.font = `normal ${weight} ${Math.round(size)}px normal "PingFang SC-Regular", "PingFang SC"`
this.ctx.setFillStyle(color)
this.ctx.setFontSize(size)return this.ctx.measureText(text).width
}// 單行文本
drawTxt({ text, x, y, size, color, weight }) {
this.ctx.save()
this.ctx.font = `normal ${weight} ${Math.round(size)}px normal "PingFang SC-Regular", "PingFang SC"`
this.ctx.setFillStyle(color)
this.ctx.setFontSize(size)
this.ctx.fillText(text, x, y)
this.ctx.restore()return this.textWidth({ text, size, color, weight })
}// 多行文本
drawMulitLineTxt({ text, x, y, size, color, weight, lineWidth, lineHeight }) {
this.ctx.save()this.ctx.font = `normal ${weight} ${Math.round(size)}px normal "PingFang SC-Regular", "PingFang SC"`
this.ctx.setFillStyle(color)
this.ctx.setFontSize(size)var temp = '', arr = []
for (var i in text.split('')) {
temp += text[i]// 如果大於行寬,輸出,重新初始化
if (this.textWidth({ text: temp, size, color, weight }) >= lineWidth) {
this.ctx.fillText(arr.join(''), x, y)temp = ''
arr = []
y += lineHeightcontinue
}// 計算到末尾
if ((parseInt(i) + 1) == text.length) {
this.ctx.fillText(arr.join(''), x * this.r, y * this.r)
break
}arr.push(text[i])
}this.ctx.restore()
}// 畫圖
drawImage({ src, x, y, w, h }) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src,
success: (res) => {
this.ctx.save()
this.ctx.drawImage(res.path, x, y, w, h)
this.ctx.restore()
resolve(this)
}
})
})
}// 圓角圖片
drawCircleImage({ src, x, y, w, h }) {
return new Promise((resolve, reject) => {
wx.getImageInfo({
src,
success: (res) => {
debug(`[報告生成圖片] 生成圓角圖片成功 src=${src} res=${JSON.stringify(res)}`)
this.ctx.save()
this.ctx.beginPath()
this.ctx.arc(w / 2 + x, h / 2 + y, w / 2, 0, Math.PI * 2, false)
this.ctx.clip()
this.ctx.drawImage(res.path, x, y, w, h)
this.ctx.restore()
resolve(this)
},
fail: (err) => {
debug(`[報告生成圖片] 生成圓角圖片失敗 src=${src} err=${err}`)
}
})
})
}// 畫圓
drawCircle({ w, h, x, y }) {
this.ctx.save()
this.ctx.beginPath()
this.ctx.arc(w / 2 + x, h / 2 + y, w / 2, 0, Math.PI * 2, false)
this.ctx.closePath()
this.ctx.restore()
}// 畫方塊
drawBlock({ w, h, x = 0, y = 0, bg = '#ffffff', r = 0 }) {
this.ctx.save()
this.ctx.beginPath()
this.ctx.moveTo(x + r, y)
this.ctx.arcTo(x + w, y, x + w, y + h, r)
this.ctx.arcTo(x + w, y + h, x, y + h, r)
this.ctx.arcTo(x, y + h, x, y, r)
this.ctx.arcTo(x, y, x + w, y, r)
this.ctx.fillStyle = bg
this.ctx.closePath()
this.ctx.fill()
this.ctx.restore()
}saveImage() {
return new Promise((resolve, reject) => {
this.ctx.draw(false, () => {
debug(`[報告生成圖片] 保存圖片 w=${this.w * 2} h=${this.h * 2} canvasId=${this.canvasId}`)
wx.canvasToTempFilePath({
canvasId: this.canvasId,
destWidth: this.w * 2,
destHeight: this.h * 2,
success: (res) => {
debug(`[報告生成圖片] 生成臨時文件成功, path=${res.tempFilePath}`)
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => {
debug('[報告生成圖片] 保存圖片成功')
wx.showToast({
title: '保存圖片成功',
icon: 'none',
duration: 2000
})
setTimeout(() => {
wx.hideToast()
resolve(this)
}, 2000)
},
fail: (err) => {
debug('[報告生成圖片] 保存圖片失敗!', err)
wx.showToast({
title: '保存圖片失敗',
icon: 'none',
duration: 2000
})
setTimeout(() => {
wx.hideToast()
resolve(this)
}, 2000)
}
})
},
fail: (err) => {
debug('[報告生成圖片] 生成臨時文件失敗!', err)
}
}, this.that)
})
})
}
}export default CanvasUtil
demo.wxml
<canvas class="my-canvas" canvas-id="diet-report-canvas" style="width:{{w}}px; height:{{h}}px"></canvas>
demo.js
// canvas id
const canvasId = 'diet-report-canvas'
// 設備像素比
const dpr = wx.getSystemInfoSync().pixelRatio
// 寬
const w = 343 * dpr
// 高
const h = getCanvasHeight() * dpr// 設置頁面canvas寬高
this.setData({ w, h })// canvas 工具
const cu = new CanvasUtil(this, { canvasId, w, h })