小程序提供了轉(zhuǎn)發(fā)給好友的接口枝誊,但是沒提供分享到朋友圈的接口顽聂。于是逻淌,只有引導(dǎo)用戶保存圖片分享到朋友圈么伯。
兩種方案:用微信 api 手動保存,用 painter恍风。
微信 api
使用原生接口的話蹦狂,大致是使用 canvas 繪制出海報,然后下載朋贬。所以重點是繪制出海報,下載的流程都是一樣的窜骄。當(dāng)然在保存圖片到相冊前锦募,還會需要獲取保存圖片到相冊的權(quán)限×诙簦總結(jié)下來就是canvas繪制糠亩,獲取保存權(quán)限虐骑,保存圖片這三個步驟。
首先來看繪制海報赎线,需要使用以下接口
- wx.createCanvasContext 創(chuàng)建 canvas context
- ctx.drawImage 繪制圖片到 canvas
- ctx.fillText 寫文字
- wx.getImageInfo 獲取網(wǎng)絡(luò)圖片的 tempFilePath
- ctx.draw canvas 繪制
最終保存下來的海報是這樣的
繪制的內(nèi)容很簡單廷没,首先就是背景圖;然后是分享者的頭像垂寥;接下來是 @ xx 邀請你 這樣一個文本描述颠黎;最后就是底部的小程序碼。
首先滞项,創(chuàng)建 canvas 畫布
<canvas canvas-id='canvas' class='canvas' :style="{height: windowHeight + 'px'}"/>
使用小程序 createCanvasContext api,需要傳入 canvasid
const ctx = wx.createCanvasContext('canvas')
然后將背景圖片繪制出來狭归,背景圖片是放在本地的圖片。
ctx.drawImage('../../../static/assets/img/poster_background.png', 0, 0, this.windowWidth, this.windowHeight)
然后寫上文字
ctx.setFontSize(12);
ctx.setFillStyle('#FFFFFF');
ctx.setTextAlign('center');
ctx.fillText(`${this.privateUserInfo.nickname} 邀您領(lǐng)取`, this.windowWidth / 2, this.transformScale(520))
這里會將原始尺寸和繪制的尺寸等比例轉(zhuǎn)換一下文判,就不贅述了过椎。再接下來就是繪制小程序碼了。由于小程序碼是帶了分享者的信息戏仓,所以必須是臨時獲取的網(wǎng)絡(luò)圖片資源疚宇,具體怎么獲取帶有分享者信息的小程序碼,會專門寫一篇文章介紹赏殃。
繪制圖片
繪制頭像與小程序碼灰嫉,這兩張圖片都是網(wǎng)絡(luò)資源,所以都要使用 wx. getImageInfo 接口將其下載下來放到微信內(nèi)存中嗓奢,然后使用其response.path 繪制讼撒。小程序并不支持直接的繪制網(wǎng)絡(luò)圖片,而且也不支持 base64圖片的繪制(雖然模擬器上會有效果)股耽。頭像的繪制還有有一個裁剪圓形頭像的過程根盒。wx.getImageInfo是異步的,所以在回調(diào)函數(shù)里繪制物蝙,當(dāng)然這不是好的方式炎滞。可以使用 promise 來解決诬乞,由于現(xiàn)在已經(jīng)不用這個代碼了册赛,就沒有去改了。
wx.getImageInfo({
src: miniProgramCodeSrc,
success: (response) => {
const miniProgramCodeSize = this.transformScale(160)
ctx.drawImage(response.path, this.transformScale(85), this.transformScale(710), miniProgramCodeSize, miniProgramCodeSize)
wx.getImageInfo({
src: this.privateUserInfo.avatar,
success: (response) => {
const avatarSize = this.transformScale(100)
//先繪制圓震嫉,裁剪成圓形圖片
ctx.save();
ctx.beginPath();
//圓的原點x坐標(biāo)森瘪,y坐標(biāo),半徑扼睬,起始弧度,終止弧度
ctx.arc(this.transformScale(320), this.transformScale(425), avatarSize / 2, 0, 2 * Math.PI);
ctx.setStrokeStyle('#ffffff');
ctx.stroke();
ctx.clip();
ctx.drawImage(response.path, this.transformScale(270), this.transformScale(375), avatarSize, avatarSize)
ctx.restore();
ctx.draw(false, () => {
this.saveToTempFilePath()
})
}
})
}
})
到這一步悴势,繪制基本就結(jié)束了窗宇。我們所要的海報內(nèi)容已經(jīng)可以在 canvas 上呈現(xiàn)了措伐,接下來就是將 canvas 的內(nèi)容保存為圖片了。值得提醒的是军俊,ctx.draw這個接口也是異步的侥加,需要在其回調(diào)中執(zhí)行下載的操作。
獲取 tempFilePath
- wx.canvasToTempFilePath 獲取整個 canvas 的tempFilePath
保存圖片最重要的就是tempFilePath了粪躬,使用canvasToTempFilePath 獲取 tempFilePath担败。需要注意的是canvasToTempFilePath接口二參需要傳入 this。
saveToTempFilePath() {
wx.canvasToTempFilePath({
canvasId: 'canvas',
success: (response) => {
//獲取相冊授權(quán)
}
}, this)
}
獲取 tempFilePath 成功后再獲取保存權(quán)限短蜕,當(dāng)然也可以先獲取保存權(quán)限氢架,再獲取tempFilePath。
獲取保存權(quán)限
首先查看是否有保存權(quán)限朋魔,有權(quán)限就可以直接保存了岖研。沒有權(quán)限就先獲取權(quán)限,再保存警检。
- wx.getSetting 查看權(quán)限列表
- wx.authorize 若沒有保存圖片權(quán)限孙援,進行授權(quán)
wx.getSetting({
success: (res) => {
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope:'scope.writePhotosAlbum',
success: () => {
this.saveImageToPhotosAlbumByWX(response.tempFilePath)
}
})
} else {
this.saveImageToPhotosAlbumByWX(response.tempFilePath)
}
}
})
保存圖片到相冊
- wx.saveImageToPhotosAlbum 保存圖片到相冊
這一步就很簡單了,萬事俱備扇雕,只差保存了拓售。調(diào)用 wx.saveImageToPhotosAlbum 即可。
saveImageToPhotosAlbumByWX(tempFilePath) {
wx.saveImageToPhotosAlbum({
filePath: tempFilePath,
complete: () => {
// 其他操作
}
})
}
到這里镶奉,使用原生 api 保存一張分享朋友圈的海報就好了础淤。
painter
painter 是什么呢?
小程序生成圖片庫哨苛,輕松通過 json 方式繪制一張可以發(fā)到朋友圈的圖片
painter 是酷家樂開源的小程序圖片生成庫鸽凶,類似 echarts,使用配置對象渲染圖片到 canvas建峭。渲染完成后回調(diào)會返回 tempFilePath,然后調(diào)用 wx.saveImageToPhotosAlbum 即可保存玻侥。保存的步驟和第一種方案一致,關(guān)鍵是獲取到 tempFilePath亿蒸。
按照其 readme 來操作就好了凑兰,由于項目是使用了 mpvue,所以使用了mpvue接入方案边锁。
使用 painter
<painter v-if="showPainter" class='canvas' @imgOK="onImgOk" :palette="palette"/>
為什么要使用 v-if 呢姑食,需要在所有數(shù)據(jù)都準備好了后再渲染 painter,否則會無限繪制砚蓬。
data() {
return {
//painter 配置數(shù)據(jù)
palette: {
width: '640rpx',
height: '1008rpx',
background: '/static/assets/img/poster_background.png',
views: [
{
type: 'image',
url: '',
css: {
top: '380rpx',
left: '320rpx',
align: 'center',
width: '100rpx',
height: '100rpx',
borderRadius: '50rpx'
}
}, {
type: 'text',
text: '',
css: {
top: '490rpx',
left: '320rpx',
align: 'center',
fontSize: '24rpx',
color: '#fff'
}
},
{
type: 'image',
url: '',
css: {
top: '690rpx',
left: '85rpx',
width: '180rpx',
height: '180rpx'
}
}
]
}
}
},
computed: {
showPainter() {
const avatar = this.palette.views[0].url
const text = this.palette.views[1].text
const qrCodeUrl = this.palette.views[2].url
return avatar !== '' && text !== '' && qrCodeUrl!== ''
}
}
在 painter繪制成功的回調(diào)里矢门,將 tempFilePath 保存起來。接下來的權(quán)限獲取和保存圖片到相冊流程就和上一個方案一致了灰蛙。但是祟剔,需要提醒的是,tempFilePath 需要放在全局變量中摩梧,不能放在data 中物延。
總結(jié)
總結(jié)一下,遇到的一些坑
- 小程序canvas不能支持 base64
- drow 有回調(diào)
- drawImage 不能直接使用網(wǎng)絡(luò)圖片
- 需要處理獲取權(quán)限仅父,用戶拒絕后的場景
最后
海報就暴露了叛薯,是的,就是漫游鯨笙纤。歡迎掃個碼體驗漫游鯨小程序耗溜,歡迎了解下漫游鯨。如果還不了解漫游鯨省容,那么點擊就能了解漫游鯨啦