欠下的生成海報(bào)的功能終于補(bǔ)上了
周末花了點(diǎn)時(shí)間把小程序版博客中的生成海報(bào)的功能給完成了,對(duì)于新手的我來說遇到的問題還是挺多的,這里簡(jiǎn)單記錄下坑。
首先看下效果圖:
還是比較簡(jiǎn)單,主要就是利用微信提供的畫布 canvas 來動(dòng)態(tài)構(gòu)造海報(bào)。引導(dǎo)用戶保存至本地相冊(cè),用于分享。
主要涉及小程序畫布和圖片相關(guān)的API,若是不太熟悉的話可以優(yōu)先參考下文檔。
首先需要準(zhǔn)備構(gòu)成海報(bào)的一些資源,比如文章的首圖,標(biāo)題,需要分享的小程序碼。對(duì)于文章的首圖,是從騰訊云的對(duì)象存儲(chǔ)中獲取,需要在開發(fā)設(shè)置中配置好 downloadFile合法域名 ,至于為什么轉(zhuǎn)戰(zhàn)騰訊云對(duì)象存儲(chǔ)可以參考 免費(fèi)的對(duì)象存儲(chǔ)——七牛云還是騰訊云
獲取圖片可直接通過 wx.getImageInfo ,對(duì)應(yīng)的API還是比較簡(jiǎn)單的:
wx.getImageInfo({ src: url, success (res) { console.log(res.path) } })
至于小程序碼,目前使用的是小程序本身的,暫時(shí)沒有動(dòng)態(tài)生成,后期會(huì)迭代。直接將小程序碼上傳至云存儲(chǔ)上,獲取時(shí)也比較簡(jiǎn)單:
wx.cloud.downloadFile({ fileID: fileID }).then(res => { console.log(res.tempFilePath) }) |
最后,其他需要在海報(bào)上展現(xiàn)的內(nèi)容,根據(jù)實(shí)際情況進(jìn)行獲取。
資源準(zhǔn)備完之后,就需要利用畫布進(jìn)行構(gòu)造海報(bào)了。
在wxml添加canvas元素,需要注意的是避免在頁面上展示,可以將位置設(shè)置在屏幕之外,比如 top:99999rpx
<view class="canvas-box"> <canvas style="width: 600px;height: 970px;" canvas-id="mycanvas" /> view> |
然后需要了解下canvas相關(guān)API和屬性了。
優(yōu)先創(chuàng)建canvas的繪圖上下文 CanvasContext 對(duì)象,然后通過CanvasContext中的屬性進(jìn)行繪制,最后通過 draw() 將之前在繪圖上下文中的描述(路徑、變形、樣式)畫到 canvas 中。具體可以參考下面的代碼,結(jié)合注釋和官方文檔很容易理解:
var context = wx.createCanvasContext('mycanvas'); context.setFillStyle('#ffffff');//設(shè)置填充色 context.fillRect(0, 0, 600, 970);//填充一個(gè)矩形。用 setFillStyle 設(shè)置矩形的填充色 context.drawImage(postImageLocal, 0, 0, 600, 300); //繪制首圖 context.drawImage(qrcodeLoal, 210, 650, 180, 180); //繪制二維碼 context.setFillStyle("#000000"); context.setFontSize(20);//設(shè)置字體大小 context.setTextAlign('center');//設(shè)置字體對(duì)齊 context.fillText("閱讀文章,請(qǐng)長(zhǎng)按識(shí)別二維碼", 300, 895); context.setFillStyle("#000000"); context.beginPath() //分割線 context.moveTo(30, 620) context.lineTo(570, 620) context.stroke(); context.setTextAlign('left'); context.setFontSize(40); if (title.lengh <= 12) { context.fillText(title, 40, 360);//文章標(biāo)題 } else { context.fillText(title.substring(0, 12), 40, 360); context.fillText(title.substring(12, 26), 40, 410); } context.setFontSize(20); if (custom_excerpt.lengh <= 26) { context.fillText(custom_excerpt, 40, 470);//文章描述 } else { context.fillText(custom_excerpt.substring(0, 26), 40, 470); context.fillText(custom_excerpt.substring(26, 50) + '...', 40, 510); } context.draw(); |
這里需要注意的是填寫文字時(shí),畫布是不會(huì)自動(dòng)換行的,所以這里需要根據(jù)字體大小和字體多少來自行控制換行。
在填充完canvas之后,通過 wx.canvasToTempFilePath 來生成圖片,并保存在臨時(shí)路徑下,具體代碼如下:
wx.canvasToTempFilePath({ canvasId: 'mycanvas', success: function(res) { var tempFilePath = res.tempFilePath; wx.hideLoading(); console.log("海報(bào)圖片路徑:" + res.tempFilePath); that.setData({ showPosterPopup: true,//展示彈窗 showPosterImage: res.tempFilePath //對(duì)應(yīng)路徑 }) }, fail: function(res) { console.log(res); } }); |
到這里,最簡(jiǎn)單的海報(bào)生成完成了,接下來就是涉及交互了。
首先利用zanui的 zan-popup 來實(shí)現(xiàn)彈出層,還是比較方便的。具體樣式就不貼了,可以直接看我的源碼。
彈出層中加載生成好的海報(bào)圖片,通過按鈕引導(dǎo)用戶保存至本地相冊(cè),在保存相冊(cè)時(shí),需要用戶授權(quán)本地相冊(cè)的權(quán)限,這里需要做好交互,當(dāng)用戶拒絕之后再次想保存時(shí),讓他重新授權(quán)。
當(dāng)用戶取消時(shí),再次提醒:
具體代碼如下,供參考:
/** * 保存海報(bào)圖片 */ savePosterImage: function() { let that = this wx.saveImageToPhotosAlbum({ filePath: that.data.showPosterImage, success(result) { console.log(result) wx.showModal({ title: '提示', content: '二維碼海報(bào)已存入手機(jī)相冊(cè),趕快分享到朋友圈吧', showCancel: false, success: function(res) { that.setData({ showPosterPopup: false }) } }) }, fail: function(err) { console.log(err); if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") { console.log("再次發(fā)起授權(quán)"); wx.showModal({ title: '用戶未授權(quán)', content: '如需保存海報(bào)圖片到相冊(cè),需獲取授權(quán).是否在授權(quán)管理中選中“保存到相冊(cè)”?', showCancel: true, success: function(res) { if (res.confirm) { console.log('用戶點(diǎn)擊確定') wx.openSetting({ success: function success(res) { console.log('打開設(shè)置', res.authSetting); wx.openSetting({ success(settingdata) { console.log(settingdata) if (settingdata.authSetting['scope.writePhotosAlbum']) { console.log('獲取保存到相冊(cè)權(quán)限成功'); } else { console.log('獲取保存到相冊(cè)權(quán)限失敗'); } } }) } }); } } }) } } }); } |
到這里,小程序的生成海報(bào)功能基本上就完成了。
其實(shí)生成海報(bào)的功能還有很多小問題,由于最近項(xiàng)目比較緊匆匆上了,后面找時(shí)間會(huì)優(yōu)化。
通過生成海報(bào)的功能,主要還是學(xué)習(xí)了畫布的API,并通過實(shí)戰(zhàn)也基本可以上手canvas,至于畫布上排版,樣式就需要自己耐心了,尤其是一些小地方。
程序上線后我才發(fā)現(xiàn),海報(bào)上的標(biāo)題,由于有中英文,所占的字符不同,所以換行的處理過于草率了,導(dǎo)致有英文的標(biāo)題在位置上存在偏差。
后期有空的話再持續(xù)改善吧~