這里是
Geek
小程序的源碼涧郊,點擊查看 github 源碼
前言
在開發(fā)小程序的過程中贯被,你是否有將頁面生成分享圖并引導(dǎo)用戶轉(zhuǎn)發(fā)至朋友圈的需求?有妆艘,那就進來看看彤灶,應(yīng)該是你想要的結(jié)果。
在分享上批旺,就目前來說幌陕,小程序是不能直接分享到朋友圈的,微信官方只開放了分享到好友和群聊的 API汽煮。對于分享到朋友圈搏熄,現(xiàn)在大多數(shù)小程序所采用的方式,就是根據(jù)不同的需求生成一張帶小程序碼的圖片引導(dǎo)用戶分享至朋友圈暇赤。
當然分享圖也可以在后臺生成搬卒,但是你懂得,基本沒有那個后臺大哥愿意為你去用代碼寫一張圖出來翎卓,所以契邀,咱們還是自給自足,??失暴。
歡迎大家使用微信掃描【組件庫小程序碼】(或者微信直接搜索組件庫演示
)查看運行效果
生成分享圖大致流程如下~
官方文檔
關(guān)于生成二維碼
- 微信官方獲取二維碼 API
- 如果每一次分享的二維碼不同坯门,需要要生成
帶參數(shù)
的二維碼 (采用接口B) - 生成的二維碼需要下載到本地
- 別忘了在
小程序微信公眾平臺后臺
-設(shè)置
-開發(fā)設(shè)置
-服務(wù)器域名
-downloadFile 合法域名
中添加域名
1. 使用 canvas 進行繪制
我們知道小程序是支持將 canvas 直接轉(zhuǎn)換為圖片的,我們可以充分利用這個先決條件
1.1 拿到設(shè)計的效果圖逗扒,我們可以先按標注計算出每個元素的寬高以及在畫布中的位置古戴,建議使用 百分比
,這樣可以對所有的屏幕大小進行適配
示例代碼如下:
const temp = 0.01;
//圖片長寬比
const scale = 1.78;
//背景圖高度
const bgScale = 0.5;
//頭像和寬的比
const avatarWidthScale = 0.368;
const avatarHeightScale = 0.117;
//頭像白色圓形背景
const avatarBgWidthScale = 0.38;
const avatarStrokeWidth = 4;
//昵稱高度比
const nicknameHeightScale = 0.34 + 5 * temp;
//第一行文字高度
const topTextScale = 0.515 + 3 * temp;
//分享內(nèi)容
const contentScale = 0.585 + 3 * temp;
const contentScale2 = 0.620 + 3 * temp;
//二維碼直徑
const qrCodeWidthScale = 0.341;
//二維碼高度
const qrCodeHeightScale = 0.69;
//極客文字
const bpbScale = 0.91 + temp * 2;
//識別文字
const decodeScale = 0.935 + temp * 2;
1.2 涉及到圖片繪制
- 本地圖片可以直接繪制
- 如果要繪制的元素中含有網(wǎng)絡(luò)圖片矩肩,需要先將圖片下載到本地现恼,不然在真機上無法顯示(親測在模擬器上可以繪制,但在 iPhone6s 真機上無法顯示)
- 貼上頭像下載代碼:
/**
* 下載頭像
*/
downloadAvatar: function () {
var that = this;
wx.downloadFile({
url: that.data.avatar,
success: function (res) {
that.setData({
avatarPath: res.tempFilePath
})
that.drawImage();
},
fail: function () {
that.showErrorModel();
}
})
},
1.3 對各個元素進行繪制
- 對于文字過長省略...黍檩,目前沒有好的辦法叉袍,暫時采用的是設(shè)置最大文字長度,超出截斷刽酱,并手動添加....
- 對于生成圓形頭像喳逛,可參考例子實現(xiàn)
drawImage: function () {
var that = this;
const ctx = wx.createCanvasContext('myCanvas', this);
var bgPath = '../../image/share-bg.png';
//設(shè)置 canvas 背景,不然生成的圖片背景會有黑色底
ctx.setFillStyle(WHITE);
ctx.fillRect(0, 0, windowWidth, windowHeight);
//繪制背景圖片
ctx.drawImage(bgPath, 0, 0, windowWidth, windowHeight * bgScale);
//頭像背景圓
ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth + avatarStrokeWidth, 0, 2 * Math.PI);
ctx.setFillStyle(WHITE);
ctx.fill();
//先繪制圓棵里,裁剪成圓形圖片
ctx.save();
ctx.beginPath();
//圓的原點x坐標润文,y坐標姐呐,半徑,起始弧度典蝌,終止弧度
ctx.arc(windowWidth / 2, avatarWidthScale / 2 * windowWidth + avatarHeightScale * windowHeight, (avatarWidthScale / 2) * windowWidth, 0, 2 * Math.PI);
ctx.setStrokeStyle(WHITE);
ctx.stroke();
ctx.clip();
//繪制頭像
//圖片路徑曙砂,左上角x坐標,左上角y坐標骏掀,寬麦轰,高
var avatarWidth = avatarWidthScale * windowWidth;//頭像半徑
ctx.drawImage(that.data.avatarPath, windowWidth * (0.5 - avatarWidthScale / 2), avatarHeightScale * windowHeight, avatarWidth, avatarWidth);
ctx.restore();
//繪制 content
ctx.setFillStyle(GRAY_COLOR);
ctx.setFontSize(18);
ctx.setTextAlign('center');
ctx.fillText(that.data.detailStr.content, windowWidth / 2, contentScale * windowHeight);
ctx.setFillStyle(GRAY_COLOR);
ctx.setFontSize(18);
ctx.setTextAlign('center');
ctx.fillText(that.data.detailStr.contentOther, windowWidth / 2, contentScale2 * windowHeight);
//繪制二維碼
ctx.drawImage(that.data.QRPath, windowWidth * (0.5 - qrCodeWidthScale / 2), qrCodeHeightScale * windowHeight, qrCodeWidthScale * windowWidth, qrCodeWidthScale * windowWidth);
console.log('font------------>' + wx.canIUse('canvasContext.font'));
//繪制 按壓提示文字
ctx.setFillStyle(TINT_COLOR);
ctx.setFontSize(14);
ctx.setTextAlign('center');
ctx.fillText(that.data.detailStr.clickToMini, windowWidth / 2, decodeScale * windowHeight);
//繪制加粗文字--------------------------------------------------------------
//繪制昵稱
that.setFontStyle(ctx, 'bold');
ctx.setFillStyle(WHITE);
ctx.setFontSize(20);
ctx.setTextAlign('center');
ctx.fillText(stringUtil.substringStr(that.data.nickname), windowWidth / 2, nicknameHeightScale * windowHeight);
//繪制文字
ctx.setFillStyle(THEME_COLOR);
ctx.setFontSize(24);
ctx.setTextAlign('center');
ctx.fillText(that.data.detailStr.tip, windowWidth / 2, topTextScale * windowHeight);
//繪制 Geek小程序
ctx.setFillStyle(TINT_COLOR);
ctx.setFontSize(16);
ctx.setTextAlign('center');
ctx.fillText(that.data.detailStr.bpbMini, windowWidth / 2, bpbScale * windowHeight);
//繪制到 canvas 上
ctx.draw(false, function () {
console.log('callback--------------->');
that.saveCanvasImage();
});
}
1.4 兼容處理
- 一些 API 屬性是在高版本才有的,比如
文字加粗
(基礎(chǔ)庫 1.9.90 開始支持砖织,低版本需做兼容處理) - 在使用之前用
wx.canIUse
判斷
/**
* 改變字體樣式
*/
setFontStyle: function (ctx, fontWeight) {
if (wx.canIUse('canvasContext.font')) {
ctx.font = 'normal ' + fontWeight + ' ' + '14px' + ' sans-serif';
}
},
1.5 不同機型適配
- 可以拿主流的幾款手機適配款侵,包括 ios 和 Android,沒有問題的話侧纯,就可以進行下一步了
2. 調(diào)整樣式
- 達到效果后修改
wxml
以及wxss
新锈,對 canvas 的樣式調(diào)整 - 確保 canvas 在屏幕可可顯示區(qū)域外,因為 canvas 的層級是最高的眶熬,我們直接在上面顯示圖片是不能顯示的妹笆,也不建議這么做(可以使用
cover-view
) - 這個自由發(fā)揮,可以將 canvas 的
position
設(shè)置為脫離文檔流(fixed
)娜氏,只要 canvas 不在屏幕顯示范圍即可拳缠,確保離可見區(qū)域足夠遠
.canvas {
width: 100%;
position: fixed;
top: 9999rpx;
left: 0;
}
3. 將 canvas 保存為圖片
- 這是最后一步,給用戶展示分享圖片的同時贸弥,用戶可以選擇保存圖片到手機相冊
3.1 注意處理用戶授權(quán)問題
- 同時處理到用戶同意和拒絕權(quán)限
//轉(zhuǎn)化為圖片
saveCanvasImage: function () {
var that = this;
wx.canvasToTempFilePath({
canvasId: 'myCanvas',
success: function (res) {
console.log(res.tempFilePath);
that.setData({
targetSharePath: res.tempFilePath,
realShow: true
})
},
complete: function () {
that.hideLoading();
}
}, this)
},
/**
* 保存到相冊
*/
saveImageTap: function () {
var that = this;
that.requestAlbumScope();
},
/**
* 檢測相冊權(quán)限
*/
requestAlbumScope: function () {
var that = this;
// 獲取用戶信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.writePhotosAlbum']) {
// 已經(jīng)授權(quán)窟坐,可以直接調(diào)用 getUserInfo 獲取頭像昵稱,不會彈框
that.saveImageToPhotosAlbum();
} else {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success(res) {
that.saveImageToPhotosAlbum();
},
fail() {
wx.showModal({
title: '提示',
content: '你需要授權(quán)才能保存圖片到相冊',
success: function (res) {
if (res.confirm) {
wx.openSetting({
success: function (res) {
if (res.authSetting['scope.writePhotosAlbum']) {
that.saveImageToPhotosAlbum();
} else {
console.log('用戶未同意獲取用戶信息權(quán)限-------->success');
}
},
fail: function () {
console.log('用戶未同意獲取用戶信息權(quán)限-------->fail');
}
})
}
}
})
}
})
}
}
})
},
3.2 保存圖片到相冊
saveImageToPhotosAlbum: function () {
var that = this;
wx.saveImageToPhotosAlbum({
filePath: that.data.targetSharePath,
success: function () {
wx.showModal({
title: '',
content: '??圖片保存成功绵疲,\n快去分享到朋友圈吧',
showCancel: false
})
that.hideDialog();
}
})
},
- 下面我將講解小程序自定義組件哲鸳,以及對保存相冊的封裝,畢竟分享的地方會很多盔憨,封裝成組件會大大簡化我們的代碼量以及工作量徙菠,這樣就可以少加點班,哈哈
- 簡要流程就介紹到這里
- 更多細節(jié)參考 Geek 小程序源代碼
- 我是源代碼郁岩,點我婿奔,點我,快點我??