Egret5.2.2版本发布微信小游戏后,在开放数据域有一个默认排行榜。这个文件夹代码+图大小就22kb。

排行榜的效果就是示范用的,很丑...带翻页。

代码如下,基本就是使用canvas渲染了一个排行榜。
好处是不需要额外新建另一个Egret项目来实现排行榜,减小了代码体积。
坏处是canvas手动绘制排行榜,没有egret的eui可视化编辑,非常的不方便。
代码很长,慢慢看....
1/** 2 * 微信开放数据域 3 * 使用 Canvas2DAPI 在 SharedCanvas 渲染一个排行榜, 4 * 并在主域中渲染此 SharedCanvas 5 */ 6 7 8 9 10 11 12 13/** 14 * 资源加载组,将所需资源地址以及引用名进行注册 15 * 之后可通过assets.引用名方式进行获取 16 */ 17var assets = { 18 icon: "openDataContext/assets/icon.png", 19 box: "openDataContext/assets/box.png", 20 panel: "openDataContext/assets/panel.png", 21 button: "openDataContext/assets/button.png", 22 title: "openDataContext/assets/rankingtitle.png" 23}; 24/** 25 * canvas 大小 26 * 这里暂时写死 27 * 需要从主域传入 28 */ 29let canvasWidth; 30let canvasHeight; 31 32/** 33 * 加载资源函数 34 * 理论上只需要加载一次,且在点击时才开始加载 35 * 最好与canvasWidht和canvasHeight数据的传入之后进行 36 */ 37preloadAssets(); 38 39//获取canvas渲染上下文 40var context = sharedCanvas.getContext("2d"); 41context.globalCompositeOperation = "source-over"; 42 43 44/** 45 * 所有头像数据 46 * 包括姓名,头像图片,得分 47 * 排位序号i会根据parge*perPageNum+i+1进行计算 48 */ 49let totalGroup = [ 50 { key: 1, name: "1111111111", url: assets.icon, scroes: 10000 }, 51 { key: 2, name: "2222222222", url: assets.icon, scroes: 9000 }, 52 { key: 3, name: "3333333", url: assets.icon, scroes: 8000 }, 53 { key: 4, name: "4444444", url: assets.icon, scroes: 7000 }, 54 { key: 5, name: "55555555", url: assets.icon, scroes: 6000 }, 55 { key: 6, name: "6666666", url: assets.icon, scroes: 5000 }, 56 { key: 7, name: "7777777", url: assets.icon, scroes: 4000 }, 57 { key: 8, name: "8888888", url: assets.icon, scroes: 3000 }, 58 { key: 9, name: "9999999", url: assets.icon, scroes: 2000 }, 59 { key: 10, name: "1010101010", url: assets.icon, scroes: 2000 }, 60 { key: 11, name: "111111111111", url: assets.icon, scroes: 2000 }, 61 { key: 12, name: "121212121212", url: assets.icon, scroes: 2000 }, 62 { key: 13, name: "13131313", url: assets.icon, scroes: 2000 }, 63 { key: 14, name: "1414141414", url: assets.icon, scroes: 2000 }, 64 { key: 15, name: "1515151515", url: assets.icon, scroes: 2000 }, 65 { key: 16, name: "1616161616", url: assets.icon, scroes: 2000 }, 66]; 67 68/** 69 * 创建排行榜 70 */ 71function drawRankPanel() { 72 //绘制背景 73 context.drawImage(assets.panel, offsetX_rankToBorder, offsetY_rankToBorder, RankWidth, RankHeight); 74 //绘制标题 75 let title = assets.title; 76 //根据title的宽高计算一下位置; 77 let titleX = offsetX_rankToBorder + (RankWidth - title.width) / 2; 78 let titleY = offsetY_rankToBorder + title.height + 50; 79 context.drawImage(title, titleX, titleY); 80 //获取当前要渲染的数据组 81 let start = perPageMaxNum * page; 82 currentGroup = totalGroup.slice(start, start + perPageMaxNum); 83 //创建头像Bar 84 drawRankByGroup(currentGroup); 85 //创建按钮 86 drawButton() 87} 88/** 89 * 根据屏幕大小初始化所有绘制数据 90 */ 91function init() { 92 //排行榜绘制数据初始化 93 RankWidth = stageWidth * 4 / 5; 94 RankHeight = stageHeight * 4 / 5; 95 barWidth = RankWidth * 4 / 5; 96 barHeight = RankWidth / perPageMaxNum; 97 offsetX_rankToBorder = (stageWidth - RankWidth) / 2; 98 offsetY_rankToBorder = (stageHeight - RankHeight) / 2; 99 preOffsetY = (RankHeight - barHeight) / (perPageMaxNum + 1); 100 101 startX = offsetX_rankToBorder + offsetX_rankToBorder; 102 startY = offsetY_rankToBorder + preOffsetY; 103 avatarSize = barHeight - 10; 104 intervalX = barWidth / 20; 105 textOffsetY = (barHeight + fontSize) / 2; 106 textMaxSize = 250; 107 indexWidth = context.measureText("99").width; 108 109 //按钮绘制数据初始化 110 buttonWidth = barWidth / 3; 111 buttonHeight = barHeight / 2; 112 buttonOffset = RankWidth / 3; 113 lastButtonX = offsetX_rankToBorder + buttonOffset - buttonWidth; 114 nextButtonX = offsetX_rankToBorder + 2 * buttonOffset; 115 nextButtonY = lastButtonY = offsetY_rankToBorder + RankHeight - 50 - buttonHeight; 116 let data = wx.getSystemInfoSync(); 117 canvasWidth = data.windowWidth; 118 canvasHeight = data.windowHeight; 119} 120 121/** 122 * 创建两个点击按钮 123 */ 124function drawButton() { 125 context.drawImage(assets.button, nextButtonX, nextButtonY, buttonWidth, buttonHeight); 126 context.drawImage(assets.button, lastButtonX, lastButtonY, buttonWidth, buttonHeight); 127} 128 129 130/** 131 * 根据当前绘制组绘制排行榜 132 */ 133function drawRankByGroup(currentGroup) { 134 for (let i = 0; i < currentGroup.length; i++) { 135 let data = currentGroup[i]; 136 drawByData(data, i); 137 } 138} 139 140/** 141 * 根据绘制信息以及当前i绘制元素 142 */ 143function drawByData(data, i) { 144 let x = startX; 145 //绘制底框 146 context.drawImage(assets.box, startX, startY + i * preOffsetY, barWidth, barHeight); 147 x += 10; 148 //设置字体 149 context.font = fontSize + "px Arial"; 150 //绘制序号 151 context.fillText(data.key + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize); 152 x += indexWidth + intervalX; 153 //绘制头像 154 context.drawImage(data.url, x, startY + i * preOffsetY + (barHeight - avatarSize) / 2, avatarSize, avatarSize); 155 x += avatarSize + intervalX; 156 //绘制名称 157 context.fillText(data.name + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize); 158 x += textMaxSize + intervalX; 159 //绘制分数 160 context.fillText(data.scroes + "", x, startY + i * preOffsetY + textOffsetY, textMaxSize); 161} 162 163/** 164 * 点击处理 165 */ 166function onTouchEnd(event) { 167 let x = event.clientX * sharedCanvas.width / canvasWidth; 168 let y = event.clientY * sharedCanvas.height / canvasHeight; 169 if (x > lastButtonX && x < lastButtonX + buttonWidth 170 && y > lastButtonY && y < lastButtonY + buttonHeight) { 171 //在last按钮的范围内 172 if (page > 0) { 173 buttonClick(0); 174 175 } 176 } 177 if (x > nextButtonX && x < nextButtonX + buttonWidth 178 && y > nextButtonY && y < nextButtonY + buttonHeight) { 179 //在next按钮的范围内 180 if ((page + 1) * perPageMaxNum < totalGroup.length) { 181 buttonClick(1); 182 } 183 } 184 185} 186/** 187 * 根据传入的buttonKey 执行点击处理 188 * 0 为上一页按钮 189 * 1 为下一页按钮 190 */ 191function buttonClick(buttonKey) { 192 let old_buttonY; 193 if (buttonKey == 0) { 194 //上一页按钮 195 old_buttonY = lastButtonY; 196 lastButtonY += 10; 197 page--; 198 renderDirty = true; 199 console.log('上一页'); 200 setTimeout(() => { 201 lastButtonY = old_buttonY; 202 //重新渲染必须标脏 203 renderDirty = true; 204 }, 100); 205 } else if (buttonKey == 1) { 206 //下一页按钮 207 old_buttonY = nextButtonY; 208 nextButtonY += 10; 209 page++; 210 renderDirty = true; 211 console.log('下一页'); 212 setTimeout(() => { 213 nextButtonY = old_buttonY; 214 //重新渲染必须标脏 215 renderDirty = true; 216 }, 100); 217 } 218 219} 220 221/////////////////////////////////////////////////////////////////// 相关缓存数据 222 223/**********************数据相关***************************/ 224 225/** 226 * 渲染标脏量 227 * 会在被标脏(true)后重新渲染 228 */ 229let renderDirty = true; 230 231/** 232 * 当前绘制组 233 */ 234let currentGroup = []; 235/** 236 * 每页最多显示个数 237 * 建议大于等于4个 238 */ 239let perPageMaxNum = 5; 240/** 241 * 当前页数,默认0为第一页 242 */ 243let page = 0; 244/***********************绘制相关*************************/ 245/** 246 * 舞台大小 247 */ 248let stageWidth; 249let stageHeight; 250/** 251 * 排行榜大小 252 */ 253let RankWidth; 254let RankHeight; 255 256/** 257 * 每个头像条目的大小 258 */ 259let barWidth; 260let barHeight; 261/** 262 * 条目与排行榜边界的水平距离 263 */ 264let offsetX_barToRank 265/** 266 * 绘制排行榜起始点X 267 */ 268let startX; 269/** 270 * 绘制排行榜起始点Y 271 */ 272let startY; 273/** 274 * 每行Y轴间隔offsetY 275 */ 276let preOffsetY; 277/** 278 * 按钮大小 279 */ 280let buttonWidth; 281let buttonHeight; 282/** 283 * 上一页按钮X坐标 284 */ 285let lastButtonX; 286/** 287 * 下一页按钮x坐标 288 */ 289let nextButtonX; 290/** 291 * 上一页按钮y坐标 292 */ 293let lastButtonY; 294/** 295 * 下一页按钮y坐标 296 */ 297let nextButtonY; 298/** 299 * 两个按钮的间距 300 */ 301let buttonOffset; 302 303/** 304 * 字体大小 305 */ 306let fontSize = 45; 307/** 308 * 文本文字Y轴偏移量 309 * 可以使文本相对于图片大小居中 310 */ 311let textOffsetY; 312/** 313 * 头像大小 314 */ 315let avatarSize; 316/** 317 * 名字文本最大宽度,名称会根据 318 */ 319let textMaxSize; 320/** 321 * 绘制元素之间的间隔量 322 */ 323let intervalX; 324/** 325 * 排行榜与舞台边界的水平距离 326 */ 327let offsetX_rankToBorder; 328/** 329 * 排行榜与舞台边界的竖直距离 330 */ 331let offsetY_rankToBorder; 332/** 333 * 绘制排名的最大宽度 334 */ 335let indexWidth; 336 337////////////////////////////////////////////////////////// 338/** 339 * 监听点击 340 */ 341wx.onTouchEnd((event) => { 342 var l = event.changedTouches.length; 343 for (var i = 0; i < l; i++) { 344 onTouchEnd(event.changedTouches[i]); 345 } 346}); 347 348 349/** 350 * 资源加载 351 */ 352function preloadAssets() { 353 var preloaded = 0; 354 var count = 0; 355 for (var asset in assets) { 356 count++; 357 var img = wx.createImage(); 358 img.onload = function () { 359 preloaded++; 360 if (preloaded == count) { 361 setTimeout(function () { 362 createScene(); 363 }, 500); 364 } 365 } 366 img.src = assets[asset]; 367 assets[asset] = img; 368 } 369} 370/** 371 * 绘制屏幕 372 * 这个函数会在加载完所有资源之后被调用 373 */ 374function createScene() { 375 if (sharedCanvas.width && sharedCanvas.height) { 376 console.log('初始化完成') 377 stageWidth = sharedCanvas.width; 378 stageHeight = sharedCanvas.height; 379 } else { 380 console.log(`sharedCanvas.width:${sharedCanvas.width} sharedCanvas.height:${sharedCanvas.height}`) 381 } 382 init(); 383 requestAnimationFrame(loop); 384} 385/** 386 * 循环函数 387 * 每帧判断一下是否需要渲染 388 * 如果被标脏,则重新渲染 389 */ 390function loop() { 391 if (renderDirty) { 392 console.log(`stageWidth :${stageWidth} stageHeight:${stageHeight}`) 393 context.setTransform(1, 0, 0, 1, 0, 0); 394 context.clearRect(0, 0, sharedCanvas.width, sharedCanvas.height); 395 drawRankPanel(); 396 renderDirty = false; 397 } 398 requestAnimationFrame(loop); 399}