最近因爲業務緣由開始接觸微信小遊戲的開發,踩了一些坑。下面開始寫一下關於遇到的一些問題以及解決方法的總結,javascript
在DOM 環境中使用Canvans 繪製圖片咱們通常是使用以下的方式:html
var img = document.getElementById('img');
ctx.drawImage(img, 10, 10);
複製代碼
drawImage 的第一個參數能夠用HTMLImageElement,HTMLCanvasElement或者HTMLVideoElement做爲參數,可是在開放數據域下不存在DOM 操做,咱們須要使用以下的方式去繪製圖片;java
let pic = wx.createImage();
pic.src = url;
// 若是是網絡圖片,則需加載完成後繪製
// pic.onload = () => {
ctx.drawImage(pic, 10, 10);
// }
複製代碼
因爲開放域不能向主域發送數據,傳統上的思路是主域須要刷新ShareCanvas並繪製到主屏上,但這樣就會致使性能上的開銷過大,僅僅用來繪製排行榜的話是十分不明智的作法,Egret 有一個髒渲染的概念,若是頁面沒有「髒」,便是沒有變化的元素,則不會從新渲染Canvans ,從而減小了重繪次數,優化了渲染性能,具體的實現思路以下:node
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);
}
複製代碼
微信小遊戲有一個十分坑的地方:4M的限制。當咱們須要繪製排行榜但又須要讓ui 與主域一致的時候就會出現很尷尬的情況:若是將ui代碼在開放域和主域都放一份,這會讓體積大大增長,若是使用的是遊戲框架,同步繪製代碼的難度也會增長。git
那麼,咱們能夠怎麼解決這個問題呢?github
個人實現思路是,開放域的存在目前也只是獲取好友或羣共玩好友的關係數據,對於大多數遊戲,只在繪製排行榜傷上有用。所以,排行榜能夠僅繪製關係數據,即,只繪製頭像、排行這一類數據,繪製時對尺寸進行比例縮放,而背景則在主域進行繪製,而後再把排行榜墊在背景上。這種方法僅適用於只繪製不那麼複雜的排行榜的需求,對於須要繪製更復雜的界面的功能來講仍是雞肋的,還沒有見到或想出一個更好的方法。數據庫
很多的小遊戲都有客服功能的需求(emmm,好比回覆公衆號圖片引導關注),可是微信的客服系統是不支持回覆圖片的,這個時候就須要本身接入客服功能。微信的發送圖片信息的body 格式以下:json
"touser":"OPENID",
"msgtype":"image",
"image":
{
"media_id":"MEDIA_ID"
}
}
複製代碼
具體實現步驟以下:小程序
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等信息api
而後咱們須要實現一個能夠上傳圖片的頁面,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 全部,如需轉載,請註明出處;