微信小程序生成海报的代码如下:
promisify文件:
module.exports = { promisify: api => { return (options, ...params) => { return new Promise((resolve, reject) => { const extras = { success: resolve, fail: reject } api({ ...options, ...extras }, ...params) }) } } }
开始:
import {promisify} from './promisify' const wxGetImageInfo = promisify(wx.getImageInfo) // 图标路径 const [localtionIconUrl, timeIconUrl, assemblyPointIconUrl] = ['/img/icons/localtion.png', '/img/icons/time.png', '/img/icons/assembly-point .png'] // 是否是大屏幕 const isLargeScreen = wx.getSystemInfoSync().windowHeight > 516 // canvas 宽、高、内边距 const [cvsW, cvsH, cvsPL, cvsPT, cvsPB] = [300, 516, 16, 22, 70] // 封面图片宽高 const [coverImgW, coverImgH, qrImgH, qrImgW] = [300, isLargeScreen ? 180 : 150, 90, 90] // 字体内边距、字体大小、字体颜色 const [fontPL, fontPT, fontSize18, fontSize14, colorBlack, colorGray, colorRed] = [55, 45, 18, 14, '#141414', '#666', 'red'] // 字体分割显示缩略 function helpFontSplit (str, lineNum = 1) { const maxChar = 12 const len = str.length let res if (len <= maxChar) {// 小于一行 res = [str] } else if (len <= maxChar * lineNum) {// 小于指定行数 res = [str.slice(0, maxChar), str.slice(maxChar, 37)] } else {//大于指定行数 let temp = [] for (let i = 0; i < lineNum; i++) { if (i === lineNum - 1) { temp.push(str.slice(maxChar * i, (i + 1) * maxChar - 3) + '...') } else { temp.push(str.slice(maxChar * i, (i + 1) * maxChar)) } } res = temp } return lineNum > 1 ? res :[res][0] } // 日期格式化 function helpFormatDate (dateArr) { if (!Array.isArray(dateArr)) { return } return dateArr.map(item => { const week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] let startArr = item.activity_start.split('-') let endArr = item.activity_end.split('-') let start = new Date(startArr.join('/')) let end = new Date(endArr.join('/')) return startArr.splice(1, 2).join('.') + week[start.getDay()] + '~' + endArr.splice(1, 2).join('.') + week[end.getDay()] }) } // canvas转换成图片 export class Canvas2Image { constructor(param, qrUrl) { this.param = param this.qrUrl = qrUrl this.isSingle = param.price_date.length == '1' } getImg (callback) { const qrUrl = this.qrUrl const coverUrl = this.param.thumb_img Promise.all([ // url是服务器地址 // icon - 1 wxGetImageInfo({ src: url+ localtionIconUrl }), // icon - 2 wxGetImageInfo({ src: url + timeIconUrl }), // icon - 3 wxGetImageInfo({ src: url+ assemblyPointIconUrl }), // 封面图 wxGetImageInfo({ src: coverUrl }), // 小程序码图 wxGetImageInfo({ src: url+ qrUrl }) ]).then(res => { callback && callback(res) }) } render (canvasId, callback) { this.getImg(res => { console.log('---图片就绪---') console.log(res) // 图片路径 const [{path: localtionIconPath}, {path: timeIconPath}, {path: assemblyPointIconPath}, {path: coverImgPath}, {path: qrImgPath}] = res const {activity_name: title, resort: resort, price_list: prices, price_date: times} = this.param const ctx = wx.createCanvasContext(canvasId) console.log('---绘图开始---') this.drawCover(ctx, coverImgPath) this.drawIcon(ctx, localtionIconPath, timeIconPath, assemblyPointIconPath) this.drawTitle(ctx, helpFontSplit(title, 2)) this.drawLocaltion(ctx, resort) this.drawTime(ctx, helpFormatDate(times)) this.drawResort (ctx, resort) this.drawQrImage (ctx, qrImgPath) this.drawPrices (ctx, prices) ctx.draw(false, function () { console.log('---canvas绘图完成---') callback && callback() }) }) } // 绘制封面 drawCover (ctx, coverImgPath) { ctx.drawImage(coverImgPath, 0, 0, coverImgW, coverImgH) } // 绘制图标 drawIcon (ctx, localtionIconPath, timeIconPath, assemblyPointIconPath) { ctx.drawImage(localtionIconPath, fontPL - 20, coverImgH + fontPT * 2.28, 15, 15) ctx.drawImage(timeIconPath, fontPL - 20, coverImgH + fontPT * 2.88, 15, 15) if (this.isSingle) { ctx.drawImage(assemblyPointIconPath, fontPL - 20, coverImgH + fontPT * 3.54, 15, 15) } else { ctx.drawImage(assemblyPointIconPath, fontPL - 20, coverImgH + fontPT * 4.45, 15, 15) } } // 绘制标题 drawTitle (ctx, title) { ctx.setTextAlign('left') // 文字居中 ctx.setFillStyle(colorBlack) // 文字颜色 ctx.setFontSize(fontSize18) // 文字字号:18px ctx.fillText(title[0], fontPL - 20, coverImgH + fontPT) title[1] && ctx.fillText(title[1], fontPL - 20, coverImgH + fontPT * 1.6) } // 绘制地点 drawLocaltion (ctx, adress) { // 活动时间、地点 ctx.setFillStyle(colorGray) // 文字颜色 ctx.setFontSize(fontSize14) // 文字字号:14px ctx.fillText('集合地点: ' + helpFontSplit(adress), fontPL, coverImgH + fontPT * 2.55) } // 绘制班期 drawTime (ctx, times) { ctx.fillText('活动时间 : ' + times[0], fontPL, coverImgH + fontPT * 3.15) if (!this.isSingle) { times[1] && ctx.fillText(times[1], fontPL + 70, coverImgH + fontPT * 3.6) times[2] && ctx.fillText(times[2], fontPL + 70, coverImgH + fontPT * 4) } } // 绘制集合地点 drawResort (ctx, resort) { if (this.isSingle) { ctx.fillText('集合地点: ' + helpFontSplit(resort), fontPL, coverImgH + fontPT * 3.8) } else { ctx.fillText('集合地点: ' + helpFontSplit(resort), fontPL, coverImgH + fontPT * 4.7) } } // 绘制小程序二维码 drawQrImage (ctx, qrImgPath) { if (isLargeScreen) { ctx.drawImage(qrImgPath, cvsW - qrImgW - cvsPL - 16, cvsH - qrImgH - cvsPB + 50, qrImgW, qrImgH) } else { ctx.drawImage(qrImgPath, cvsW - qrImgW - cvsPL + 10, cvsH - qrImgH - cvsPB + 10, qrImgW - 10, qrImgH - 10) } } // 绘制价格 drawPrices (ctx, prices) { const priceLabel = ['', '成人价: ', '儿童价: ', '老人价: '] const baseNum = 5.3 const increment = 0.6 if (Array.isArray(prices)) { prices.forEach((item, index) => { ctx.setFillStyle(colorGray) ctx.fillText(priceLabel[item.type], fontPL - 20, coverImgH + fontPT * (baseNum + index * increment)) ctx.setFillStyle(colorRed) ctx.fillText('¥' + item.price, fontPL + 35, coverImgH + fontPT * (baseNum + index * increment)) }) } ctx.stroke() } } // 保存至本地 export function saveCanvasImage2Local(canvasId, callback) { console.log('---准备保存到本地---') const wxCanvasToTempFilePath = promisify(wx.canvasToTempFilePath) const wxSaveImageToPhotosAlbum = promisify(wx.saveImageToPhotosAlbum) wxCanvasToTempFilePath({ canvasId: canvasId }, this).then(res => { console.log('---保存到本地就绪---') callback && callback() return wxSaveImageToPhotosAlbum({ filePath: res.tempFilePath }) }).then(res => { wx.showModal({...{ title: '', content: '这是一个模态弹窗', cancelText: '取消', cancelColor: '#505050', confirmText: '确定', confirmColor: '#ff4558', showCancel: true, success: function(res) { if (res.confirm) { console.log('用户点击确定') } else if (res.cancel) { console.log('用户点击取消') } } }, ...config}) // wx.showToast({ // title: '已保存到相册' // }) }) }