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);
}
