前言:這陣子接手小程序的開發,也算是遇到一些問題,學習過程中也做一些自己的總結。主要的一個需求就是在用戶進行轉發的時候轉發圖片都不一樣,而且其中數據是要隨着更改的。第一思路用到的就是canvas,查了一些相關資料,參照思路,最后也是實現了產品所要的功能。其他也不多說,在下面直接上一些實現思路和代碼吧。PS:因為我用的Taro框架,是react寫法,標簽就不換了,看官們能看懂的,就是原生小程序標簽變大小寫
(這里是實現分享轉發的時候每次生成不一樣的分享圖片)
HTML部分(CSS就不放上來了)
<View className='index'> // 我是自定義生成的那張分享圖哦,會隨着數據變化而變化~ <View className='save-view'> <Canvas className='poster' canvasId='poster' style='width:250px;height:200px;'></Canvas> </View> <CoverView>我是這個頁面要展示的內容 <Button className='share-btn' open-type="share">我是分享按鈕</Button> </CoverView> </View>
這里要注意:1.因為是分享轉發帶的圖片,按官方比例5:4。建議canvas的大小也是這個比例,例如500*400rpx;
2.在首頁主要展示的內容用cover-view原生組件包起來,為的就是在進入頁面覆蓋掉canvas讓用戶看不到;
3.這里建議最外層的cover-view采用fixed方式,因為有些手機識別z-index其實不是很好;
JS部分
state: IState = { recordList: null, // 列表數據 imgUrl: '', // 生成分享圖鏈接 }; // data變量區 // 獲得canvas圖片信息 ImageInfo(path: any) { return new Promise((resolve, reject) => { Taro.getImageInfo( { src: path, success: function (res) { resolve(res) }, fail: function (res) { reject(res) } } ) }) } // 繪畫Canvas-分享圖 drawTitle(datas: any, title: string) { new Promise((resolve, reject) => { let rpx = 0 Taro.getSystemInfo({ success: function (res) { rpx = res.windowWidth / 375 } }) // 這里計算rpx是為了適配更多的手機,畢竟dpr值都不一樣。可以要也可以不要 this.ImageInfo('https://static.jingzhuan.cn/WeChat/longtou/share-img-bg.png').then(res => { // 這里注意,因為canvas畫圖片是需要圖片信息的,即臨時路徑類,最好是先把背景圖放在網絡上再通過小程序API生成獲取路徑 // 獲取畫布 const cvsCtx = Taro.createCanvasContext('poster', this) cvsCtx.drawImage(res.path, 0, 0, 250 * rpx, 200 * rpx) // 繪制背景底圖 cvsCtx.setFontSize(16) cvsCtx.setFillStyle('#FFFFFF') cvsCtx.fillText(title, (250 - cvsCtx.measureText(title).width) * rpx / 2, 26 * rpx, 120 * rpx) // 計算標題文字所占寬度好做絕對居中計算 for (let b = 0; b < 3; b++) { cvsCtx.setFontSize(14) // 設置字體大小 cvsCtx.setFillStyle('#941D11') // 設置字體顏色 cvsCtx.fillText(datas[b].name, 95 * rpx, (88 + b * 38) * rpx, 70 * rpx) cvsCtx.setFontSize(14) if (datas[b].rise_percent > 0) { // 判斷數據是否需要改變字體顏色 cvsCtx.setFillStyle('#FB4949') } else { cvsCtx.setFillStyle('#00CC66') } cvsCtx.fillText(`${datas[b].rise_percent}%`, 180 * rpx, (88 + b * 38) * rpx, 70 * rpx) // 繪制文字所在位置 } cvsCtx.draw(true) }) resolve() }).then(() => { this.generateUrl() // 當頁面的canvas畫成功后就調取生成臨時路徑 }) } // 截取canvas生成臨時路徑 async generateUrl() { const that = this setTimeout(() => { Taro.canvasToTempFilePath({ x: 0, y: 0, width: 500, // 截取的寬度 height: 400, // 截取的高度 destWidth: 500, // 生成的圖片寬度 destHeight: 400, // 生成的圖片高度 canvasId: 'poster', // 生成對象的canvasid success: function (res) { that.goQiniu(res.tempFilePath) // 生成圖片成功后調取上傳到網絡上 }, fail: function (res) { console.log('繪制臨時路徑失敗') } }) }, 1000) // 設置1秒定時是防止canvas畫一半,一般1秒是差不多的 } // 上傳臨時圖片到七牛獲取網絡鏈接(這里是七牛SDK的上傳方法,其他服務器都有對應的,根據情況而改變哦~) async goQiniu(imgUrl: any) { const that = this const res = await getQiniu({ key: 'sig' }) qiniuUploader.upload(imgUrl, (res: any) => { let audioURL = (這里寫你們的服務器域名進行拼接,例如:https://www.baidu.com/) + res.key that.state.imgUrl = audioURL // 最后生成的網絡連接,是可以直接在網頁上打開看到圖片的,然后復制給到全局變量給分享的時候獲取 }, (error: any) => { console.error('error: ' + JSON.stringify(error)); }, { uptoken: res.token, region: 'ECN', // 華東區 key: `longtou/share/${Math.random().toString(36).slice(2, 10)}.png` // 自動生成隨機命名 }, ) } // 自定義分享 onShareAppMessage() {return { title: '我是分享標題~好不好看~', path: shareUrl, imageUrl: this.state.imgUrl, // 生成的分享圖賦值給到小程序自定義分享圖鏈接 success: function () { // 轉發成功 console.log(shareUrl) }, fail: function () { // 轉發失敗 console.log('轉發失敗') } } }
以上就是主要的思路代碼,最后注意要在進入頁面后就執行canvas畫圖,即在onlaod的時候執行drawTitle方法,這樣就避免在頁面加載完后用戶馬上點擊分享轉發canvas圖還沒畫完的情況
具體效果就如下(demo可能比較粗糙哈哈):