/**
需要繪制的內(nèi)容有:
> 圖片
1枝缔、背景圖
2瞬雹、頭像
3粗蔚、邀請(qǐng)語(yǔ)
4靡菇、商品圖
5昌讲、二維碼
6国夜、指紋
>文字
1、0
2短绸、元搶購(gòu)
3车吹、原價(jià)¥999.00
4、商品標(biāo)題
5醋闭、長(zhǎng)按識(shí)別二維碼 進(jìn)入活動(dòng)
6窄驹、此二維碼已安全認(rèn)證,可以放心掃描*/
// 繪制圓形頭像
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,防止邊界出現(xiàn)的問(wèn)題
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'
}
// 文字內(nèi)容
let content = {
zero: shareInfo.price,
mTitle: '元搶購(gòu)',
oPrice: `原價(jià)¥${shareInfo.cprice}`,
pTitle: shareInfo.prize,
tip: '長(zhǎng)按識(shí)別二維碼 進(jìn)入活動(dòng)',
scan: '此二維碼已安全認(rèn)證证逻,可以放心掃描',
}
// 將圖片地址轉(zhuǎn)為臨時(shí)圖片
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){ // 這里有個(gè)異步問(wèn)題
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) // 推薦語(yǔ)
// 商品圖需要做寬高自適應(yīng)居中
// 圖片以高度為自適應(yīng)
// 如果自適應(yīng)高度之后的圖片乐埠,超出ui的最大寬度,則再次進(jìn)行寬度自適應(yīng)調(diào)整和高度自適應(yīng)調(diào)整
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
/**文字繪制*/
// 商品標(biāo)題
ctx.setFillStyle('#333333')//文字顏色:默認(rèn)黑色
ctx.setFontSize(30*rate) // 文字大小
ctx.setTextAlign('left') // 文字居中
textWrap(ctx,content.pTitle,103*rate, 858*rate,50*rate,660*rate)
// 長(zhǎng)按識(shí)別二維碼 進(jìn)入活動(dòng)
ctx.setFontSize(24*rate)
ctx.setTextAlign('center') // 文字居中
ctx.fillText(content.tip, 375*rate, 1084*rate)
// 此二維碼已安全認(rèn)證囚企,可以放心掃描
ctx.setTextAlign('left') // 文字居中
ctx.setFontSize(20*rate)
ctx.setFillStyle('#88AE5C')//文字顏色:默認(rèn)黑色
ctx.fillText(content.scan, 220*rate, 1118*rate)
// 活動(dòng)標(biāo)題
// 活動(dòng)標(biāo)題由三部分組成:( 紅色0 元搶購(gòu) 原價(jià) )這邊需要根據(jù)原價(jià)進(jìn)行偏移控制
// 原價(jià)
// 紅色0
let zeroDeviation = 0 // 紅色字體偏移
let zero = '0'
let oirginDeviation = 0 // 原價(jià)偏移
let oirgin = '原價(jià)¥0'
// content.zero = 65650
content.zero = content.zero.toString() // 蘋果手機(jī)必須字符串!!!!!!
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){ // 兼容舊數(shù)據(jù)沒(méi)有cprice字段
// content.oPrice = '原價(jià)¥043434'
ctx.setFontSize(34*rate)
ctx.setFillStyle('#666666')//文字顏色:默認(rèn)黑色
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)
// 元搶購(gòu)
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)
// 元搶購(gòu)
ctx.setFontSize(44*rate)
ctx.setFillStyle('#333333')
ctx.fillText(content.mTitle, 248*rate+zeroDeviation+50, 410*rate)
ctx.draw()
}
setTimeout(()=>{
if(that.data.shareImgFlag){ // 如果彈窗了丈咐,但是畫布還沒(méi)生成,這提醒下
wx.showToast({
title: '生成海報(bào)中...',
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 () {
// 導(dǎo)出圖片錯(cuò)誤
/*wx.showModal({
title: '導(dǎo)出圖片時(shí)出錯(cuò)',
content: '請(qǐng)重新嘗試龙宏!',
})*/
},
complete: function () {
wx.hideLoading()
}
},that)
},1000)
}
}
})
}
}
export default drawCanvas
總結(jié):中間涉及到比較坑的是標(biāo)題位移計(jì)算(發(fā)現(xiàn)數(shù)學(xué)能力現(xiàn)在倒退到小學(xué)水平了 lol)棵逊,還有一個(gè)兼容問(wèn)題:ctx.measureText(str)必須是字符串格式!R铩歹河!開發(fā)過(guò)程發(fā)現(xiàn)str為number類型,蘋果手機(jī)沒(méi)有反應(yīng)花吟,安卓可以秸歧,坑得一批,找了大半天~
效果