轉自IMWeb社群,作者:結一,原文連結
為了吸引更多的使用者,設計好一個分享海報還是很有必要的。而小程式要生成一個海報還是有點坑的,下面分享下我們打卡小程式的一些經驗。
分享海報的效果圖如下:
製作要求:
- 海報以彈窗形式展現,各種手機型號都可以正常顯示
- 海報的內容由背景圖、日期、隨機的名言警句、活動的二維碼及使用者的參加活動的資訊
- 海報儲存的圖片大小為 iphone 6 的兩倍圖(750 * 1334)
由於看到的彈窗圖片與儲存的圖片是兩種大小,所以一開始看了些網上的其他教程,建議是搞兩個 canvas 一個大的一個小的。實際過程中,採用了一個大的 canvas ,讓其偏離視窗顯示區域(不可見)並生成臨時檔案,彈窗的圖片再使用 img 元件,引入臨時檔案,設定其高度;而儲存的時候則直接下載臨時檔案。
雖然是實現了,但是後來在優化的過程中,這個方案也重新設計了。下面具體介紹下優化過的方案:
- 優先使用一個 canvas 繪製二維碼;
- 彈窗的圖片即為一個 canvas;
- 分享的圖片為該 canvas 匯出的大圖片;
- 為了達到最佳效果,名言警句的換行錄入時就處理好。
設計彈窗的圖片比例
由於最後海報的圖片大小為 iphone 6 的兩倍圖(750 * 1334),所以這裡彈窗的圖片也即是 canvas 的大小,設計為對應的尺寸的某個比例。
彈窗圖片的高度 = 視窗的高度 - 上下留白 - 按鈕的高度 - 圖片與按鈕的距離
imgHeight = 100vh - 40rpx * 2 - 50rpx - 15rpx
彈窗圖片的寬度 / 彈窗圖片的高度 = 750 / 1334
彈窗圖片的寬度 = (750 / 1334) * 彈窗圖片的高度
複製程式碼
由於畫素只能是整數,所以這樣繪製出來的圖片可能底部會有1px的空白,所以在設定高度的時候可以再減掉 1px,這不會影響視覺效果。
繪製背景圖
如果是網路圖片,繪製背景圖之前一定要先下載該圖片,可通過 wx.getImageInfo
或 wx. downloadFile
下載圖片,下載成功後將其塞進臨時地址,然後使用 wx canvas 的 drawImage
繪製。注意如果地址是 base64 的話, gif 是不行的。
繪製二維碼
繪製二維碼換了好幾個庫,每個在安卓下面生成的二維碼都會頻現失敗。查了好些資料,說是安卓繪製的時候要設定個 setTimeout,於是最終選擇了weapp-qrcode,修改了其繪製的函式,增加了setTimeout(還真別說,加上二維碼繪製就成功了)。
ctx.draw(false, function (e) {
setTimeout(() => { // 修改增加的
options.callback && options.callback(e)
}, 20);
})
複製程式碼
另:目前這些繪製小程式二維碼的庫都是在一個單獨的新 canvas 中完成的,只要對原始碼稍作修改,就可以提供另一個介面,直接在一個現有的 canvas (表示 canvas 中一開始繪製了其他內容) 中繪製。
如果二維碼掃不出來,則表示二維碼繪製出了問題。但安卓微信 6.7.2 版本本身有個 bug,二維碼本身是沒有問題,它卻不能識別。不過升級下微信版本就好了。
儲存圖片
- 先要獲取使用者是否開啟使用者授權相簿
- 如果沒有許可權,則彈窗提示開通許可權,如果有許可權直接呼叫
saveImageToPhotosAlbum
介面儲存圖片 - 如果彈窗提示接受開通許可權,則呼叫
saveImageToPhotosAlbum
介面儲存圖片 - 如果彈窗提示拒絕則再次彈窗是否去設定開通許可權,如果是則進入設定許可權
// 先嚐試儲存
trySaveImg() {
const _this = this;
// 獲取使用者是否開啟使用者授權相簿
wx.getSetting({
success(res) {
// 如果沒有則獲取授權
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
_this.saveImg();
},
fail() {
// 如果使用者拒絕過或沒有授權,則再次開啟授權視窗
// (ps:微信api又改了現在只能通過button才能開啟授權設定,以前通過openSet就可開啟,下面有開啟授權的button彈窗程式碼)
wx.showModal({
title: '獲取許可權失敗',
content: '是否開啟設定頁,允許小程式儲存圖片到你的相簿',
success: () => {
wx.openSetting({
success (sRes) {
if (sRes.authSetting['scope.writePhotosAlbum']) {
setTimeout(() => {
_this.saveImg();
}, 200);
}
},
});
},
});
},
});
} else {
// 有則直接儲存
_this.saveImg();
}
},
});
},
// 正式儲存
saveImg() {
const { tempImgPath } = this.data;
wx.showLoading({
title: '正在儲存中...', // 提示的內容,
mask: true, // 顯示透明蒙層,防止觸控穿透,
});
wx.saveImageToPhotosAlbum({
filePath: tempImgPath,
success() {
wx.showToast({
title: '儲存成功',
icon: 'success',
duration: 2000,
mask: true,
});
},
fail() {
wx.showToast({
title: '儲存失敗',
icon: 'none',
duration: 2000,
mask: true,
});
},
});
},
複製程式碼
效能注意
經實踐測試整個繪製過程其實還是很快的,但是如果有儲存臨時檔案操作( wx.canvasToTempFilePath
),那麼這個操作一般得佔一半時間左右。除此之外,有個 measureText api,用來測量文字的長度,這個在實現自動換行的時候用得到,但是比較耗效能。