前言
最近由於業務原因開始接觸微信小遊戲的開發,踩了一些坑。下面開始寫一下關於遇到的一些問題以及解決方法的總結,
一、開放資料域繪製圖片問題
在DOM 環境中使用Canvans 繪製圖片我們一般是使用如下的方式:
var img = document.getElementById(`img`);
ctx.drawImage(img, 10, 10);
複製程式碼
drawImage 的第一個引數可以用HTMLImageElement,HTMLCanvasElement或者HTMLVideoElement作為引數,但是在開放資料域下不存在DOM 操作,我們需要使用如下的方式去繪製圖片;
let pic = wx.createImage();
pic.src = url;
// 如果是網路圖片,則需載入完成後繪製
// pic.onload = () => {
ctx.drawImage(pic, 10, 10);
// }
複製程式碼
二、開放資料域效能問題
由於開放域不能向主域傳送資料,傳統上的思路是主域需要重新整理ShareCanvas並繪製到主屏上,但這樣就會導致效能上的開銷過大,僅僅用來繪製排行榜的話是十分不明智的做法,Egret 有一個髒渲染的概念,如果頁面沒有“髒”,即是沒有變化的元素,則不會重新渲染Canvans ,從而減少了重繪次數,優化了渲染效能,具體的實現思路如下:
let requestAnimationFrameID; // 記錄requestAnimationFrame的ID
let isDirty = true; // 標誌是否為髒
/**
* 每次渲染時,判斷是否“髒”了,若是,則重新渲染
*/
function render() {
if (isDirty) {
context.setTransform(1, 0, 0, 1, 0, 0); // 座標系復位
context.clearRect(0, 0, sharedCanvas.width, sharedCanvas.height); // 清除 Canvans 畫布
drawElements(); //繪製排行榜,或者其他元素
isDirty = false;
}
requestAnimationFrame(render);
}
複製程式碼
三、UI 同步問題
微信小遊戲有一個十分坑的地方:4M的限制。當我們需要繪製排行榜但又需要讓ui 與主域一致的時候就會出現很尷尬的狀況:如果將ui程式碼在開放域和主域都放一份,這會讓體積大大增加,如果使用的是遊戲框架,同步繪製程式碼的難度也會增加。
那麼,我們可以怎麼解決這個問題呢?
我的實現思路是,開放域的存在目前也只是獲取好友或群共玩好友的關係資料,對於大多數遊戲,只在繪製排行榜傷上有用。因此,排行榜可以僅繪製關係資料,即,只繪製頭像、排行這一類資料,繪製時對尺寸進行比例縮放,而背景則在主域進行繪製,然後再把排行榜墊在背景上。這種方法僅適用於只繪製不那麼複雜的排行榜的需求,對於需要繪製更復雜的介面的功能來說還是雞肋的,尚未見到或想出一個更好的方法。
四、客服訊息回回復圖片功能
不少的小遊戲都有客服功能的需求(emmm,比如回覆公眾號圖片引導關注),但是微信的客服系統是不支援回覆圖片的,這個時候就需要自己接入客服功能。微信的傳送圖片資訊的body 格式如下:
"touser":"OPENID",
"msgtype":"image",
"image":
{
"media_id":"MEDIA_ID"
}
}
複製程式碼
具體實現步驟如下:
- 新增臨時素材
當我們想向使用者傳送一張圖片時,並不能隨心所欲地使用任意圖片地址,如上json所示,微信只提供一個mediaid,這個mediaid是我們呼叫新增臨時素材介面提交到微信伺服器上之後,返回的一個圖片標識,介面如下:
https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
複製程式碼
引數說明:
access_token: 呼叫介面憑證
type:媒體型別,固定填寫為 image
media:form-data中媒體檔案標識,有filename、filelength、content-type等資訊
然後我們需要實現一個可以上傳圖片的頁面,node端接收併傳送到微信伺服器上,如果成功獲取到mediaid之後我們就可以存放在資料庫或快取上對應appid 的地方以便後續傳送圖片使用
let token = wechat.getMiniAccessToken(); // 自己實現獲取當前小程式/小遊戲的access token的函式,appid 要對應,否則mediaid是不會回覆到使用者的
const options = {
url: `https://api.weixin.qq.com/cgi-bin/media/upload?access_token=${token.access_token}&type=image`,
formData: body.fields,
};
request.post(options, (err, res, data) => {
// 將回傳的物件中的mediaid 對應appid存放
})
複製程式碼
- 接收使用者發來的訊息
這一步我們需要先配置好伺服器,參考微信伺服器接入指引這篇文章,需要注意的是,只有在驗證url是否合法的情況下,才會帶有echostr 引數,以此我們可以判斷當前請求是否為伺服器驗證,如果帶有echostr 引數,我們只需要在確認簽名無誤之後,把echostr 原樣返回就可以了。如果沒有echostr引數,則是微信轉發過來的使用者發來的訊息,此時我們就要進入下一步去傳送圖片了。
const {
signature, timestamp, nonce, echostr,
} = this.query;
const { body } = this.request;
if (echostr) { // 用於配置客服伺服器使用
const result = wechat.checkSign(timestamp, nonce, signature); // 校驗簽名是否正確
this.body = result ? echostr : `err signature`;
} else {
wechat.sengMsg(body); // 進入下一步傳送圖片
this.body = `success`;
}
複製程式碼
- 向使用者傳送圖片
上一步中我們接收到微信轉發過來的使用者訊息,具體格式可以參考微信客服訊息 這篇文章,我們可以獲取到傳送過來使用者,只需要請求微信的介面,就可以把訊息推送給該使用者了。
const mediaId = `需要傳送的圖片的mediaid`;
let token = wechat.getMiniAccessToken(); // 當前小程式/小遊戲的access token
const options = {
url: `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${token.access_token}`,
body: {
touser: data.FromUserName, // 需要傳送的使用者
msgtype: `image`,
image: {
media_id: mediaId,
},
},
json: true,
};
request.post(options, (err, res, data) => {
// 傳送之後的處理函式
});
複製程式碼
結語
筆者對於微信小遊戲也只能算是剛入門,以上內容也只是幾天開發完之後的一些經驗,不算成熟,如有錯誤,希望指正,互相成長,謝謝。
以上內容歸本人EvontGoh 所有,如需轉載,請註明出處;