一 . 效果
這是借用女神照生成的分享的海報歇万,圖片來自網(wǎng)絡。
新增了poster組件和更新圖片自適應
二 . 準備
準備兩張圖片連接,最好是自己開發(fā)賬號驗證的https圖片鏈接。
三 . 實現(xiàn)思路
其實就是canvas實現(xiàn)方式燃观,首先要就是定義一個canvas容器,把容器放在中間便瑟,圖片也要動態(tài)計算大小居中缆毁,顯示下面的文字和二維碼也是要根據(jù)容器動態(tài)去改變,這就是大概的實現(xiàn)思路到涂。
四 . 實現(xiàn)代碼
利用微信小程序canvas生成海報分享圖片脊框,這個生成圖片排版和適配不同尺寸的手機是一個難點,特別是圖片適應問題践啄,我處理的方法是動態(tài)獲取容器的寬度進行適應就是利用微信API wx.createSelectorQuery(),不知道還有沒有更好的辦法可以請教浇雹。
1.下載頭像
為了確保圖片下載完成之后,再回調其它方法執(zhí)行下一步屿讽。
getAvaterInfo: function (cardInfo) {//cardInfo是傳入的信息參數(shù)昭灵,按實際需要。
wx.showLoading({ title: '生成中...',mask: true,});
var that = this;
if (cardInfo.CardInfo.Avater) {
wx.downloadFile({
url: '圖片路徑',
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var avaterSrc = res.tempFilePath;
that.getQrCode(avaterSrc, cardInfo);
}else{
wx.showToast({
title: '頭像下載失敺ヌ浮烂完!',
icon:'none',
duration: 2000,
success:function(){
that.getQrCode(avaterSrc = "", cardInfo);//回調另一個圖片下載
}
})
}
}
})
} else {
wx.hideLoading();
that.getQrCode(avaterSrc = "", cardInfo);//回調另一個圖片下載
}
},
2.下載二維碼
二維碼下載一樣的道理,就是先下載完成诵棵,再進行繪圖抠蚣。
getQrCode: function (avaterSrc, cardInfo) {
wx.showLoading({ title: '生成中...', mask: true, });
var that = this;
if (cardInfo.CardInfo.QrCode) {
wx.downloadFile({
url: cardInfo.CardInfo.QrCode,
success: function (res) {
wx.hideLoading();
if (res.statusCode === 200) {
var codeSrc = res.tempFilePath;
that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的繪圖方法
} else {
wx.showToast({
title: '二維碼下載失敗履澳!',
icon: 'none',
duration: 2000,
success: function () {
var codeSrc = "";
that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的繪圖方法
}
})
}
}
})
} else {
wx.hideLoading();
var codeSrc = "";
that.sharePosteCanvas(cardInfo, avaterSrc, codeSrc);//真正的繪圖方法
}
},
3.繪制分享海報
這里才是canvas實現(xiàn)繪制的過程
sharePosteCanvas: function (cardInfo, avaterSrc, codeSrc) {
wx.showLoading({
title: '生成中...',
mask: true,
})
var that = this;
const ctx = wx.createCanvasContext('myCanvas');
var width = "";
wx.createSelectorQuery().select('#canvas-container').boundingClientRect(function (rect) {
var height = rect.height;
var right = rect.right;
width = rect.width * 0.8;
var left = rect.left + 5;
ctx.setFillStyle('#fff');
ctx.fillRect(0, 0, rect.width, height);
//頭像
if (avaterSrc) {
ctx.drawImage(avaterSrc, left, 20, width, width);
ctx.setFontSize(14);
ctx.setFillStyle('#fff');
ctx.setTextAlign('left');
}
if (cardInfo.TagList.length > 0) {
ctx.fillText(cardInfo.TagList[0].TagName, left + 20, width - 4); //標簽
const metrics = ctx.measureText(cardInfo.TagList[0].TagName); //測量文本信息
ctx.stroke();
ctx.rect(left + 10, width - 20, metrics.width + 40, 25);
ctx.setFillStyle('rgba(255,255,255,0.4)');
ctx.fill();
}
if (cardInfo.CardInfo.Name) {
ctx.setFontSize(14);
ctx.setFillStyle('#000');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.CardInfo.Name, left, width + 60); //姓名
}
if (cardInfo.CardInfo.Position) {
ctx.setFontSize(12);
ctx.setFillStyle('#666');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.CardInfo.Position, left, width + 85); //職位
}
if (cardInfo.CardInfo.Mobile) {
ctx.setFontSize(12);
ctx.setFillStyle('#666');
ctx.setTextAlign('left');
ctx.fillText(cardInfo.CardInfo.Mobile, left, width + 105); //電話
}
if (cardInfo.CardInfo.Company) {
// 公司名稱
const CONTENT_ROW_LENGTH = 24; // 正文 單行顯示字符長度
let [contentLeng, contentArray, contentRows] = that.textByteLength(cardInfo.CardInfo.Company, CONTENT_ROW_LENGTH);
ctx.setTextAlign('left');
ctx.setFillStyle('#000');
ctx.setFontSize(10);
let contentHh = 22 * 1;
for (let m = 0; m < contentArray.length; m++) {
ctx.fillText(contentArray[m], left, width + 150 + contentHh * m);
}
}
// 繪制二維碼cardInfo.CardInfo.QrCode
if (codeSrc) {
ctx.drawImage(codeSrc, left + 150, width + 40, width / 3, width / 3)
ctx.setFontSize(10);
ctx.setFillStyle('#000');
ctx.setTextAlign('right');
ctx.fillText("微信掃碼或長按識別", left + 235, width + 150);
}
}).exec()
setTimeout(function () {
ctx.draw(); 這里有個需要注意就是嘶窄,這個方法是在繪制完成之后在調用怀跛,不然容易其它被覆蓋。
wx.hideLoading();
}, 1000)
},
4.多行顯示文字
這個函數(shù)就是需要多行顯示文字的時候進行折行柄冲,就是切分為數(shù)組吻谋。
textByteLength(text, num) { // text為傳入的文本 num為單行顯示的字節(jié)長度
let strLength = 0; // text byte length
let rows = 1;
let str = 0;
let arr = [];
for (let j = 0; j < text.length; j++) {
if (text.charCodeAt(j) > 255) {
strLength += 2;
if (strLength > rows * num) {
strLength++;
arr.push(text.slice(str, j));
str = j;
rows++;
}
} else {
strLength++;
if (strLength > rows * num) {
arr.push(text.slice(str, j));
str = j;
rows++;
}
}
}
arr.push(text.slice(str, text.length));
return [strLength, arr, rows] // [處理文字的總字節(jié)長度,每行顯示內容的數(shù)組羊初,行數(shù)]
},
5.保存繪制生成圖片
這一步就是最后把canvas生成圖片了滨溉,大功告成什湘。
//點擊保存到相冊
saveShareImg: function () {
var that = this;
wx.showLoading({
title: '正在保存',
mask: true,
})
setTimeout(function () {
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
success: function (res) {
wx.hideLoading();
var tempFilePath = res.tempFilePath;
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
success(res) {
wx.showModal({
content: '圖片已保存到相冊长赞,趕緊曬一下吧~',
showCancel: false,
confirmText: '好的',
confirmColor: '#333',
success: function (res) {
if (res.confirm) { }
},
fail: function (res) { }
})
},
fail: function (res) {
wx.showToast({
title: res.errMsg,
icon: 'none',
duration: 2000
})
}
})
}
});
}, 1000);
},
五 . 填坑
1.圖片要提前下載
這里面還有一個問題就是,圖片要提前下載完之后再繪圖闽撤,不然圖片顯示不出來得哆,可以把下載圖片的方法單獨拎出來,然后下載圖片后回調繪圖方法哟旗。
- ctx.draw()
這個方法是在繪制完成之后在調用贩据,不然容易其它被覆蓋。
這樣就大功告成了闸餐,有問題可以和聯(lián)系作者饱亮,一起進步。
喜歡就點點喜歡鼓勵
DEMO路徑:https://github.com/kingbuwu/poster
demo上封裝了poster組件和顯示頭圖圖片自適應