/**
需要绘制的内容有:
> 图片
1、背景图
2、头像
3、邀请语
4、商品图
5、二维码
6、指纹
>文字
1、0
2、元抢购
3、原价¥999.00
4、商品标题
5、长按识别二维码 进入活动
6、此二维码已安全认证,可以放心扫描*/
// 绘制圆形头像
function circleImg(ctx, img, x, y, r) {
ctx.save();
var d = 2 * r;
var cx = x + r;
var cy = y + r;
ctx.arc(cx, cy, r, 0, 2 * Math.PI);
ctx.clip();
ctx.drawImage(img, x, y, d, d);
ctx.restore();
}
// 文字换行
function textWrap(ctx, str, initX, initY, lineHeight, cavWithd) {
let lineWidth = 0;
let canvasWidth = cavWithd ? cavWithd : 240;
let lastSubStrIndex = 0;
if (!lineHeight) {
lineHeight = 20;
}
let _addLineHeight = 0;
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width;
if (lineWidth > canvasWidth - initX) { //减去initX,防止边界出现的问题
ctx.fillText(str.substring(lastSubStrIndex, i), initX, initY);
initY += lineHeight;
lineWidth = 0;
lastSubStrIndex = i;
_addLineHeight += lineHeight;
//++lineNum
}
if (i == str.length - 1) {
ctx.fillText(str.substring(lastSubStrIndex, i + 1), initX, initY);
}
}
return _addLineHeight;
}
let drawCanvas = function (that, shareInfo) {
if(that.data.resultimg){
return
}
let userInfoData = wx.getStorageSync('userInfoData') || {}
// 图片
let img = {
bg: 'https://dahoutai.side.vip/project/activity/theme/poster/wx-share-bg2.jpg',
avatar: shareInfo.avatar || 'https://dahoutai.side.vip/project/app/memberCard/default-avatar.png',
text: 'https://dahoutai.side.vip/project/activity/theme/poster/text.png',
goods: shareInfo.goods,
logo: userInfoData.brandlogo,
gou: 'https://dahoutai.side.vip/project/activity/theme/poster/gou.png',
qrcode: shareInfo.qrcode,
fingerprint: 'https://dahoutai.side.vip/project/activity/theme/poster/two-code.png'
}
// 文字内容
let content = {
zero: shareInfo.price,
mTitle: '元抢购',
oPrice: `原价¥${shareInfo.cprice}`,
pTitle: shareInfo.prize,
tip: '长按识别二维码 进入活动',
scan: '此二维码已安全认证,可以放心扫描',
}
// 将图片地址转为临时图片
let num = 0
let goodsRate = 1 // 商品图宽高比例
let logoRate = 1 // logo比例
for (let i in img) {
wx.getImageInfo({
src: img[i],
success: function (res) {
if(i == 'goods'){
goodsRate = res.height/res.width
}
if(i == 'logoRate'){
logoRate = res.height/res.width
}
img[i] = res.path
++ num
if(num == 8){ // 这里有个异步问题
console.log('开始绘图')
// 绘制canvas
let rate = .5 // 缩小比例
let ctx = wx.createCanvasContext('myCanvas',that)
/**图片绘制*/
ctx.drawImage(img.bg,0,0,750*rate,1334*rate) // 背景
circleImg(ctx,img.avatar,30*rate,139*rate,33*rate) // 绘制头像
ctx.drawImage(img.text,86*rate,139*rate,632*rate,68*rate) // 推荐语
// 商品图需要做宽高自适应居中
// 图片以高度为自适应
// 如果自适应高度之后的图片,超出ui的最大宽度,则再次进行宽度自适应调整和高度自适应调整
let goodsMaxWidth = 560*rate, // 商品ui最大宽度
goodsMaxHeight = 372*rate, // 商品ui最大高度
goodsWidth = 372/goodsRate*rate,
goodsHeight = 372*rate,
goodsDeviationX = 0, // X轴偏移
goodsDeviationY = 0 // Y轴偏移
if( goodsWidth > goodsMaxWidth){
goodsHeight = goodsHeight * (goodsMaxWidth/goodsWidth)
goodsWidth = goodsMaxWidth
goodsDeviationY = (goodsMaxHeight - goodsHeight)/2
}else {
goodsDeviationX = (goodsMaxWidth - goodsWidth)/2
}
ctx.drawImage(img.goods,95*rate+goodsDeviationX,436*rate+goodsDeviationY,goodsWidth,goodsHeight) // 商品图
ctx.drawImage(img.qrcode,243*rate,937*rate,100*rate,100*rate) // 二维码
ctx.drawImage(img.fingerprint,426*rate,937*rate,100*rate,100*rate) // 指纹
ctx.drawImage(img.gou,190*rate, 1097*rate,24*rate,24*rate) // 勾
ctx.drawImage(img.logo,275*rate,0*rate,200*rate,114*rate) // logo
/**文字绘制*/
// 商品标题
ctx.setFillStyle('#333333')//文字颜色:默认黑色
ctx.setFontSize(30*rate) // 文字大小
ctx.setTextAlign('left') // 文字居中
textWrap(ctx,content.pTitle,103*rate, 858*rate,50*rate,660*rate)
// 长按识别二维码 进入活动
ctx.setFontSize(24*rate)
ctx.setTextAlign('center') // 文字居中
ctx.fillText(content.tip, 375*rate, 1084*rate)
// 此二维码已安全认证,可以放心扫描
ctx.setTextAlign('left') // 文字居中
ctx.setFontSize(20*rate)
ctx.setFillStyle('#88AE5C')//文字颜色:默认黑色
ctx.fillText(content.scan, 220*rate, 1118*rate)
// 活动标题
// 活动标题由三部分组成:( 红色0 元抢购 原价 )这边需要根据原价进行偏移控制
// 原价
// 红色0
let zeroDeviation = 0 // 红色字体偏移
let zero = '0'
let oirginDeviation = 0 // 原价偏移
let oirgin = '原价¥0'
// content.zero = 65650
content.zero = content.zero.toString() // 苹果手机必须字符串!!!!!!
ctx.setFontSize(54*rate)
let _zeroDeviation = parseFloat(ctx.measureText(zero).width)
zeroDeviation = parseFloat(ctx.measureText(content.zero).width)
zeroDeviation = (zeroDeviation-_zeroDeviation)/2
if(shareInfo.cprice){ // 兼容旧数据没有cprice字段
// content.oPrice = '原价¥043434'
ctx.setFontSize(34*rate)
ctx.setFillStyle('#666666')//文字颜色:默认黑色
let _oirginDeviation = parseFloat(ctx.measureText(oirgin).width)
oirginDeviation = parseFloat(ctx.measureText(content.oPrice).width)
oirginDeviation = (oirginDeviation - _oirginDeviation)/2
ctx.fillText(content.oPrice, 400*rate+zeroDeviation-oirginDeviation, 406*rate)
// 绘制删除线
ctx.beginPath();
ctx.setStrokeStyle('#666666')
ctx.setLineWidth(1)
ctx.moveTo(506*rate+zeroDeviation-oirginDeviation, 392*rate)
ctx.lineTo(506*rate+zeroDeviation+oirginDeviation, 392*rate)
ctx.closePath();
ctx.stroke()
// 红色0
ctx.setTextAlign('left')
ctx.setFontSize(54*rate)
ctx.setFillStyle('#FF0237')
ctx.fillText(content.zero, 196*rate-zeroDeviation-oirginDeviation, 416*rate)
// 元抢购
ctx.setFontSize(44*rate)
ctx.setFillStyle('#333333')
ctx.fillText(content.mTitle, 248*rate+zeroDeviation-oirginDeviation, 410*rate)
ctx.draw()
}else {
// 红色0
ctx.setTextAlign('left')
ctx.setFontSize(54*rate)
ctx.setFillStyle('#FF0237')
ctx.fillText(content.zero, 196*rate-zeroDeviation+50, 416*rate)
// 元抢购
ctx.setFontSize(44*rate)
ctx.setFillStyle('#333333')
ctx.fillText(content.mTitle, 248*rate+zeroDeviation+50, 410*rate)
ctx.draw()
}
setTimeout(()=>{
if(that.data.shareImgFlag){ // 如果弹窗了,但是画布还没生成,这提醒下
wx.showToast({
title: '生成海报中...',
mask: true,
icon: 'loading'
})
}
let rate = 2
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 375,
height: 667,
destWidth: 375*rate,
destHeight: 667*rate,
canvasId: 'myCanvas',
success: function (res) {
that.setData({
resultimg: res.tempFilePath
})
wx.hideLoading()
console.log('绘图成功')
},
fail: function () {
// 导出图片错误
/*wx.showModal({
title: '导出图片时出错',
content: '请重新尝试!',
})*/
},
complete: function () {
wx.hideLoading()
}
},that)
},1000)
}
}
})
}
}
export default drawCanvas
总结:中间涉及到比较坑的是标题位移计算(发现数学能力现在倒退到小学水平了 lol),还有一个兼容问题:ctx.measureText(str)必须是字符串格式!!!开发过程发现str为number类型,苹果手机没有反应,安卓可以,坑得一批,找了大半天~