Egret5.2.2版本發布微信小游戲后,在開放數據域有一個默認排行榜。這個文件夾代碼+圖大小就22kb。
排行榜的效果就是示范用的,很丑...帶翻頁。
代碼如下,基本就是使用canvas渲染了一個排行榜。
好處是不需要額外新建另一個Egret項目來實現排行榜,減小了代碼體積。
壞處是canvas手動繪制排行榜,沒有egret的eui可視化編輯,非常的不方便。
代碼很長,慢慢看....
/** * 微信開放數據域 * 使用 Canvas2DAPI 在 SharedCanvas 渲染一個排行榜, * 並在主域中渲染此 SharedCanvas */ /** * 資源加載組,將所需資源地址以及引用名進行注冊 * 之后可通過assets.引用名方式進行獲取 */ var assets = { icon: "openDataContext/assets/icon.png", box: "openDataContext/assets/box.png", panel: "openDataContext/assets/panel.png", button: "openDataContext/assets/button.png", title: "openDataContext/assets/rankingtitle.png" }; /** * canvas 大小 * 這里暫時寫死 * 需要從主域傳入 */ let canvasWidth; let canvasHeight; /** * 加載資源函數 * 理論上只需要加載一次,且在點擊時才開始加載 * 最好與canvasWidht和canvasHeight數據的傳入之后進行 */ preloadAssets(); //獲取canvas渲染上下文 var context = sharedCanvas.getContext("2d"); context.globalCompositeOperation = "source-over"; /** * 所有頭像數據 * 包括姓名,頭像圖片,得分 * 排位序號i會根據parge*perPageNum+i+1進行計算 */ let totalGroup = [ { key: 1, name: "1111111111", url: assets.icon, scroes: 10000 }, { key: 2, name: "2222222222", url: assets.icon, scroes: 9000 }, { key: 3, name: "3333333", url: assets.icon, scroes: 8000 }, { key: 4, name: "4444444", url: assets.icon, scroes: 7000 }, { key: 5, name: "55555555", url: assets.icon, scroes: 6000 }, { key: 6, name: "6666666", url: assets.icon, scroes: 5000 }, { key: 7, name: "7777777", url: assets.icon, scroes: 4000 }, { key: 8, name: "8888888", url: assets.icon, scroes: 3000 }, { key: 9, name: "9999999", url: assets.icon, scroes: 2000 }, { key: 10, name: "1010101010", url: assets.icon, scroes: 2000 }, { key: 11, name: "111111111111", url: assets.icon, scroes: 2000 }, { key: 12, name: "121212121212", url: assets.icon, scroes: 2000 }, { key: 13, name: "13131313", url: assets.icon, scroes: 2000 }, { key: 14, name: "1414141414", url: assets.icon, scroes: 2000 }, { key: 15, name: "1515151515", url: assets.icon, scroes: 2000 }, { key: 16, name: "1616161616", url: assets.icon, scroes: 2000 }, ]; /** * 創建排行榜 */ function drawRankPanel() { //繪制背景 context.drawImage(assets.panel, offsetX_rankToBorder, offsetY_rankToBorder, RankWidth, RankHeight); //繪制標題 let title = assets.title; //根據title的寬高計算一下位置; let titleX = offsetX_rankToBorder + (RankWidth - title.width) / 2; let titleY = offsetY_rankToBorder + title.height + 50; context.drawImage(title, titleX, titleY); //獲取當前要渲染的數據組 let start = perPageMaxNum * page; currentGroup = totalGroup.slice(start, start + perPageMaxNum); //創建頭像Bar drawRankByGroup(currentGroup); //創建按鈕 drawButton() } /** * 根據屏幕大小初始化所有繪制數據 */ function init() { //排行榜繪制數據初始化 RankWidth = stageWidth * 4 / 5; RankHeight = stageHeight * 4 / 5; barWidth = RankWidth * 4 / 5; barHeight = RankWidth / perPageMaxNum; offsetX_rankToBorder = (stageWidth - RankWidth) / 2; offsetY_rankToBorder = (stageHeight - RankHeight) / 2; preOffsetY = (RankHeight - barHeight) / (perPageMaxNum + 1); startX = offsetX_rankToBorder + offsetX_rankToBorder; startY = offsetY_rankToBorder + preOffsetY; avatarSize = barHeight - 10; intervalX = barWidth / 20; textOffsetY = (barHeight + fontSize) / 2; textMaxSize = 250; indexWidth = context.measureText("99").width; //按鈕繪制數據初始化 buttonWidth = barWidth / 3; buttonHeight = barHeight / 2; buttonOffset = RankWidth / 3; lastButtonX = offsetX_rankToBorder + buttonOffset - buttonWidth; nextButtonX = offsetX_rankToBorder + 2 * buttonOffset; nextButtonY = lastButtonY = offsetY_rankToBorder + RankHeight - 50 - buttonHeight; let data = wx.getSystemInfoSync(); canvasWidth = data.windowWidth; canvasHeight = data.windowHeight; } /** * 創建兩個點擊按鈕 */ function drawButton() { context.drawImage(assets.button, nextButtonX, nextButtonY, buttonWidth, buttonHeight); context.drawImage(assets.button, lastButtonX, lastButtonY, buttonWidth, buttonHeight); } /** * 根據當前繪制組繪制排行榜 */ function drawRankByGroup(currentGroup) { for (let i = 0; i < currentGroup.length; i++) { let data = currentGroup[i]; drawByData(data, i); } } /** * 根據繪制信息以及當前i繪制元素 */ function drawByData(data, i) { let x = startX; //繪制底框 context.drawImage(assets.box, startX, startY + i * preOffsetY, barWidth, barHeight); x += 10; //設置字體 context.font = fontSize + "px Arial"; //繪制序號 context.fillText(data.key + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize); x += indexWidth + intervalX; //繪制頭像 context.drawImage(data.url, x, startY + i * preOffsetY + (barHeight - avatarSize) / 2, avatarSize, avatarSize); x += avatarSize + intervalX; //繪制名稱 context.fillText(data.name + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize); x += textMaxSize + intervalX; //繪制分數 context.fillText(data.scroes + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize); } /** * 點擊處理 */ function onTouchEnd(event) { let x = event.clientX * sharedCanvas.width / canvasWidth; let y = event.clientY * sharedCanvas.height / canvasHeight; if (x > lastButtonX && x < lastButtonX + buttonWidth && y > lastButtonY && y < lastButtonY + buttonHeight) { //在last按鈕的范圍內 if (page > 0) { buttonClick(0); } } if (x > nextButtonX && x < nextButtonX + buttonWidth && y > nextButtonY && y < nextButtonY + buttonHeight) { //在next按鈕的范圍內 if ((page + 1) * perPageMaxNum < totalGroup.length) { buttonClick(1); } } } /** * 根據傳入的buttonKey 執行點擊處理 * 0 為上一頁按鈕 * 1 為下一頁按鈕 */ function buttonClick(buttonKey) { let old_buttonY; if (buttonKey == 0) { //上一頁按鈕 old_buttonY = lastButtonY; lastButtonY += 10; page--; renderDirty = true; console.log('上一頁'); setTimeout(() => { lastButtonY = old_buttonY; //重新渲染必須標臟 renderDirty = true; }, 100); } else if (buttonKey == 1) { //下一頁按鈕 old_buttonY = nextButtonY; nextButtonY += 10; page++; renderDirty = true; console.log('下一頁'); setTimeout(() => { nextButtonY = old_buttonY; //重新渲染必須標臟 renderDirty = true; }, 100); } } /////////////////////////////////////////////////////////////////// 相關緩存數據 /**********************數據相關***************************/ /** * 渲染標臟量 * 會在被標臟(true)后重新渲染 */ let renderDirty = true; /** * 當前繪制組 */ let currentGroup = []; /** * 每頁最多顯示個數 * 建議大於等於4個 */ let perPageMaxNum = 5; /** * 當前頁數,默認0為第一頁 */ let page = 0; /***********************繪制相關*************************/ /** * 舞台大小 */ let stageWidth; let stageHeight; /** * 排行榜大小 */ let RankWidth; let RankHeight; /** * 每個頭像條目的大小 */ let barWidth; let barHeight; /** * 條目與排行榜邊界的水平距離 */ let offsetX_barToRank /** * 繪制排行榜起始點X */ let startX; /** * 繪制排行榜起始點Y */ let startY; /** * 每行Y軸間隔offsetY */ let preOffsetY; /** * 按鈕大小 */ let buttonWidth; let buttonHeight; /** * 上一頁按鈕X坐標 */ let lastButtonX; /** * 下一頁按鈕x坐標 */ let nextButtonX; /** * 上一頁按鈕y坐標 */ let lastButtonY; /** * 下一頁按鈕y坐標 */ let nextButtonY; /** * 兩個按鈕的間距 */ let buttonOffset; /** * 字體大小 */ let fontSize = 45; /** * 文本文字Y軸偏移量 * 可以使文本相對於圖片大小居中 */ let textOffsetY; /** * 頭像大小 */ let avatarSize; /** * 名字文本最大寬度,名稱會根據 */ let textMaxSize; /** * 繪制元素之間的間隔量 */ let intervalX; /** * 排行榜與舞台邊界的水平距離 */ let offsetX_rankToBorder; /** * 排行榜與舞台邊界的豎直距離 */ let offsetY_rankToBorder; /** * 繪制排名的最大寬度 */ let indexWidth; ////////////////////////////////////////////////////////// /** * 監聽點擊 */ wx.onTouchEnd((event) => { var l = event.changedTouches.length; for (var i = 0; i < l; i++) { onTouchEnd(event.changedTouches[i]); } }); /** * 資源加載 */ function preloadAssets() { var preloaded = 0; var count = 0; for (var asset in assets) { count++; var img = wx.createImage(); img.onload = function () { preloaded++; if (preloaded == count) { setTimeout(function () { createScene(); }, 500); } } img.src = assets[asset]; assets[asset] = img; } } /** * 繪制屏幕 * 這個函數會在加載完所有資源之后被調用 */ function createScene() { if (sharedCanvas.width && sharedCanvas.height) { console.log('初始化完成') stageWidth = sharedCanvas.width; stageHeight = sharedCanvas.height; } else { console.log(`sharedCanvas.width:${sharedCanvas.width} sharedCanvas.height:${sharedCanvas.height}`) } init(); requestAnimationFrame(loop); } /** * 循環函數 * 每幀判斷一下是否需要渲染 * 如果被標臟,則重新渲染 */ function loop() { if (renderDirty) { console.log(`stageWidth :${stageWidth} stageHeight:${stageHeight}`) context.setTransform(1, 0, 0, 1, 0, 0); context.clearRect(0, 0, sharedCanvas.width, sharedCanvas.height); drawRankPanel(); renderDirty = false; } requestAnimationFrame(loop); }