美文网首页
微信小游戏排行榜

微信小游戏排行榜

作者: 旧时袋 | 来源:发表于2018-09-02 11:06 被阅读0次

    子域index.js代码如下:

    import * as Consts from './consts'
    
    const PAGE_SIZE = 6;
    const ITEM_HEIGHT = 125;
    
    const dataSorter = (gameDatas, field = Consts.OpenDataKeys.Grade) => {
        return gameDatas.sort((a, b) => {
            const kvDataA = a.KVDataList.find(kvData => kvData.key === Consts.OpenDataKeys.Grade);
            const kvDataB = b.KVDataList.find(kvData => kvData.key === Consts.OpenDataKeys.Grade);
            const gradeA = kvDataA ? parseInt(kvDataA.value || 0) : 0;
            const gradeB = kvDataB ? parseInt(kvDataB.value || 0) : 0;
            return gradeA > gradeB ? -1 : gradeA < gradeB ? 1 : 0;
        });
    }
    
    class RankListRenderer
    {
        constructor()
        {
            this.totalPage = 0;
            this.currPage = 0;
            this.gameDatas = [];    //https://developers.weixin.qq.com/minigame/dev/document/open-api/data/UserGameData.html
            this.init();
        }
    
        init()
        {
            this.canvas = wx.getSharedCanvas();
            this.ctx = this.canvas.getContext('2d');
            this.ctx.imageSmoothingEnabled = true;
            this.ctx.imageSmoothingQuality = "high";
        }
    
        listen()
        {
            //msg -> {action, data}
            wx.onMessage(msg => {
                console.log("ranklist wx.onMessage", msg);
                switch(msg.action)
                {
                    case Consts.DomainAction.FetchFriend:
                        this.fetchFriendData();
                        break;
    
                    case Consts.DomainAction.FetchGroup:
                        if(!msg.data)
                        {
                            return;
                        }
                        this.fetchGroupData(msg.data);
                        break;
    
                    case Consts.DomainAction.Paging:
                        if(!this.gameDatas.length)
                        {
                            return;
                        }
                        const delta = msg.data;
                        const newPage = this.currPage + delta;
                        if(newPage < 0)
                        {
                            console.log("已经是第一页了");
                            return;
                        }
                        if(newPage + 1 > this.totalPage)
                        {
                            console.log("没有更多了");
                            return;
                        }
                        this.currPage = newPage;
                        this.showPagedRanks(newPage);
                        break;
    
                    default:
                        console.log(`未知消息类型:msg.action=${msg.action}`);
                        break;
                }
            });
        }
    
        fetchGroupData(shareTicket)
        {
            //取出群同玩成员数据
            wx.getGroupCloudStorage({
                shareTicket,
                keyList:[
                    Consts.OpenDataKeys.Grade,
                ],
                success:res => {
                    console.log("wx.getGroupCloudStorage success", res);
                    const dataLen = res.data.length;
                    this.gameDatas = dataSorter(res.data);
                    this.currPage = 0;
                    this.totalPage = Math.ceil(dataLen / PAGE_SIZE);
                    if(dataLen)
                    {
                        this.showPagedRanks(0);
                    }
                },
                fail:res => {
                    console.log("wx.getGroupCloudStorage fail", res);
                },
            });
        }
    
        fetchFriendData()
        {
            //取出所有好友数据
            wx.getFriendCloudStorage({
                keyList:[
                    Consts.OpenDataKeys.Grade,
                ],
                success:res => {
                    console.log("wx.getFriendCloudStorage success", res);
                    const dataLen = res.data.length;
                    this.gameDatas = dataSorter(res.data);
                    this.currPage = 0;
                    this.totalPage = Math.ceil(dataLen / PAGE_SIZE);
                    if(dataLen)
                    {
                        this.showPagedRanks(0);
                    }
                },
                fail:res => {
                    console.log("wx.getFriendCloudStorage fail", res);
                },
            });
        }
    
        showPagedRanks(page)
        {
            const pageStart = page * PAGE_SIZE;
            const pagedData = this.gameDatas.slice(pageStart, pageStart + PAGE_SIZE);
            const pageLen = pagedData.length;
    
            this.ctx.clearRect(0, 0, 1000, 1000);
            for(let i = 0, len = pagedData.length; i < len; i++)
            {
                this.drawRankItem(this.ctx, i, pageStart + i + 1, pagedData[i], pageLen);
            }
        }
    
        //canvas原点在左上角
        drawRankItem(ctx, index, rank, data, pageLen)
        {
            const avatarUrl = data.avatarUrl.substr(0, data.avatarUrl.length - 1) + "132";
            const nick = data.nickname.length <= 10 ? data.nickname : data.nickname.substr(0, 10) + "...";
            const kvData = data.KVDataList.find(kvData => kvData.key === Consts.OpenDataKeys.Grade);
            const grade = kvData ? kvData.value : 0;
            const itemGapY = ITEM_HEIGHT * index;
            //名次
            ctx.fillStyle = "#D8AD51";
            ctx.textAlign = "right";
            ctx.baseLine = "middle";
            ctx.font = "70px Helvetica";
            ctx.fillText(`${rank}`, 90, 80 + itemGapY);
    
            //头像
            const avatarImg = wx.createImage();
            avatarImg.src = avatarUrl;
            avatarImg.onload = () => {
                if(index + 1 > pageLen)
                {
                    return;
                }
                ctx.drawImage(avatarImg, 120, 10 + itemGapY, 100, 100);
            };
    
            //名字
            ctx.fillStyle = "#777063";
            ctx.textAlign = "left";
            ctx.baseLine = "middle";
            ctx.font = "30px Helvetica";
            ctx.fillText(nick, 235, 80 + itemGapY);
    
            //分数
            ctx.fillStyle = "#777063";
            ctx.textAlign = "left";
            ctx.baseLine = "middle";
            ctx.font = "30px Helvetica";
            ctx.fillText(`${grade}分`, 620, 80 + itemGapY);
    
            //分隔线
            const lineImg = wx.createImage();
            lineImg.src = 'subdomain/images/llk_x.png';
            lineImg.onload = () => {
                if(index + 1 > pageLen)
                {
                    return;
                }
                ctx.drawImage(lineImg, 14, 120 + itemGapY, 720, 1);
            };
        }
    }
    
    const rankList = new RankListRenderer();
    rankList.listen();
    

    主域:

    import {appdata} from './appdata'
    import {POP_UI_BASE} from './common/ui/pop_ui_base'
    import {pop_mgr, UI_CONFIG} from "./common/ui/pop_mgr"
    import {TimerMgr} from "./common/timer/timer_mgr"
    import * as utils from "./common/util"
    import * as wxapi from "./common/wxapi"
    import * as Audio from "./common/audio/audioplayer"
    
    const {ccclass, property} = cc._decorator;
    @ccclass
    export class RankView2 extends POP_UI_BASE {
    
        @property(cc.Sprite)
        img_head: cc.Sprite = null;
    
        @property(cc.Label)
        txt_name: cc.Label = null;
    
        @property(cc.Sprite)
        img_rank: cc.Sprite = null;
    
        timerId:number;
        isDirty:boolean;
        rankTexture:cc.Texture2D;
        rankSpriteFrame:cc.SpriteFrame;
    
        on_show(...params)
        {
            const appUserInfo = appdata.appUserInfo;
            const wxUserInfo = appdata.wxUserInfo;
            const avatarUrl = wxUserInfo.avatarUrl132;
            if(avatarUrl.length > 0)
            {
                this.txt_name.string = wxUserInfo.nickName;
                utils.load_external_img(this.img_head, avatarUrl, "png");
            }
    
            //只能在主域设置大小, 且要先于赋值到sprite才起作用
            const sharedCanvas = wxapi.wxOpenData.wxGetSharedCanvas();
            sharedCanvas.width = this.img_rank.node.width;
            sharedCanvas.height = this.img_rank.node.height;
    
            this.rankTexture = new cc.Texture2D();
            this.rankSpriteFrame = new cc.SpriteFrame();
            
            //拿好友排行榜
            this.isDirty = true;
            wxapi.wxOpenData.wxPostMessageToSubDomain({
                action:wxapi.WxDomainAction.FetchFriend,
            });
            this.timerId = TimerMgr.getInst().loop(0.1, utils.gen_handler(this.updateRankList, this));
        }
    
        on_hide() 
        {
            this.rankTexture = null;
            this.rankSpriteFrame = null;
            this.isDirty = false;
            TimerMgr.getInst().remove(this.timerId);
        }
    
        updateRankList()
        {
            if(!this.isDirty)
            {
                return;
            }
            const sharedCanvas = wxapi.wxOpenData.wxGetSharedCanvas();
            this.rankTexture.initWithElement(sharedCanvas);
            this.rankTexture.handleLoadedTexture();
            this.rankSpriteFrame.setTexture(this.rankTexture);
            this.img_rank.spriteFrame = this.rankSpriteFrame;
        }
    
        onTouchPageBtn(event, delta)
        {
            this.isDirty = true;
            wxapi.wxOpenData.wxPostMessageToSubDomain({
                action:wxapi.WxDomainAction.Paging,
                data:parseInt(delta),
            });
        }
    
        onTouchGroupRank()
        {
            wxapi.wxShare.share({
                title:"分享文本", 
                imageUrl:"shareimg/bg02.png",
                query:`openID=${appdata.appUserInfo.openid}`,
            }, utils.gen_handler((shareTickets:string[]) => {
                if(!shareTickets || !shareTickets.length)
                {
                    console.log('本次分享无shareTicket');
                    return;
                }
                const shareTicket = shareTickets[0];
                this.isDirty = true;
                wxapi.wxOpenData.wxPostMessageToSubDomain({
                    action:wxapi.WxDomainAction.FetchGroup,
                    data:shareTicket,
                });
            }));
        }
    }
    

    排行榜滑动和翻页

    主域:

    import * as Consts from "./consts"
    import {appdata} from './appdata'
    import {POP_UI_BASE} from './common/ui/pop_ui_base'
    import {pop_mgr, UI_CONFIG} from "./common/ui/pop_mgr"
    import {TimerMgr} from "./common/timer/timer_mgr"
    import * as utils from "./common/util"
    import * as wxapi from "./common/wxapi"
    import * as Audio from "./common/audio/audioplayer"
    
    const {ccclass, property} = cc._decorator;
    @ccclass
    export class RankView2 extends POP_UI_BASE {
        @property(cc.Sprite)
        img_rank: cc.Sprite = null;
    
        timerId:number;
        isDirty:boolean;
        rankTexture:cc.Texture2D;
        rankSpriteFrame:cc.SpriteFrame;
    
        on_show(...params)
        {
            //只能在主域设置大小, 且要先于赋值到sprite才起作用
            const sharedCanvas = wxapi.wxOpenData.wxGetSharedCanvas();
            sharedCanvas.width = this.img_rank.node.width;
            sharedCanvas.height = this.img_rank.node.height;
    
            this.rankTexture = new cc.Texture2D();
            this.rankSpriteFrame = new cc.SpriteFrame();
            
            //拿好友排行榜
            this.isDirty = true;
            wxapi.wxOpenData.wxPostMessageToSubDomain({
                action:wxapi.WxDomainAction.FetchFriend,
            });
            this.timerId = TimerMgr.getInst().loop(0.1, utils.gen_handler(this.updateRankList, this));
            this.img_rank.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        }
    
        on_hide() 
        {
            this.rankTexture = null;
            this.rankSpriteFrame = null;
            this.isDirty = false;
            TimerMgr.getInst().remove(this.timerId);
            this.img_rank.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        }
    
        onTouchMove(event:cc.Event.EventTouch)
        {
            const deltaY = event.getDeltaY();
            // console.log("rank touchmove:", deltaY);
            this.isDirty = true;
            wxapi.wxOpenData.wxPostMessageToSubDomain({
                action:wxapi.WxDomainAction.Paging,
                data:deltaY,
            });
        }
    
        updateRankList()
        {
            if(!this.isDirty)
            {
                return;
            }
            const sharedCanvas = wxapi.wxOpenData.wxGetSharedCanvas();
            this.rankTexture.initWithElement(sharedCanvas);
            this.rankTexture.handleLoadedTexture();
            this.rankSpriteFrame.setTexture(this.rankTexture);
            this.img_rank.spriteFrame = this.rankSpriteFrame;
        }
    
        onTouchGroupRank()
        {
            wxapi.wxShare.share({
                title:"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
                imageUrl:"shareimg/bg02.png",
                query:`openID=${appdata.appUserInfo.openid}`,
            }, utils.gen_handler((shareTickets:string[]) => {
                if(!shareTickets || !shareTickets.length)
                {
                    console.log('本次分享无shareTicket');
                    return;
                }
                const shareTicket = shareTickets[0];
                this.isDirty = true;
                wxapi.wxOpenData.wxPostMessageToSubDomain({
                    action:wxapi.WxDomainAction.FetchGroup,
                    data:shareTicket,
                });
            }));
        }
    }
    

    子域:

    import * as Consts from './consts'
    
    const PAGE_SIZE = 8;
    const ITEM_WIDTH = 750;
    const ITEM_HEIGHT = 125;
    
    const dataSorter = (gameDatas, field = Consts.OpenDataKeys.Grade) => {
        return gameDatas.sort((a, b) => {
            const kvDataA = a.KVDataList.find(kvData => kvData.key === Consts.OpenDataKeys.Grade);
            const kvDataB = b.KVDataList.find(kvData => kvData.key === Consts.OpenDataKeys.Grade);
            const gradeA = kvDataA ? parseInt(kvDataA.value || 0) : 0;
            const gradeB = kvDataB ? parseInt(kvDataB.value || 0) : 0;
            return gradeA > gradeB ? -1 : gradeA < gradeB ? 1 : 0;
        });
    }
    
    class RankListRenderer {
        constructor() {
            this.offsetY = 0;
            this.maxOffsetY = 0;
            this.gameDatas = [];    //https://developers.weixin.qq.com/minigame/dev/document/open-api/data/UserGameData.html
            this.init();
        }
    
        init() {
            this.canvas = wx.getSharedCanvas();
            this.ctx = this.canvas.getContext('2d');
            this.ctx.imageSmoothingEnabled = true;
            this.ctx.imageSmoothingQuality = "high";
        }
    
        listen() {
            //msg -> {action, data}
            wx.onMessage(msg => {
                //console.log("ranklist wx.onMessage", msg);
                switch (msg.action) {
                    case Consts.DomainAction.FetchFriend:
                        this.fetchFriendData();
                        break;
    
                    case Consts.DomainAction.FetchGroup:
                        if (!msg.data) {
                            return;
                        }
                        this.fetchGroupData(msg.data);
                        break;
    
                    case Consts.DomainAction.Paging:
                        if (!this.gameDatas.length) {
                            return;
                        }
                        const deltaY = msg.data;
                        const newOffsetY = this.offsetY + deltaY;
                        if (newOffsetY < 0) {
                            // console.log("前面没有更多了");
                            return;
                        }
                        if (newOffsetY + PAGE_SIZE * ITEM_HEIGHT > this.maxOffsetY) {
                            // console.log("后面没有更多了");
                            return;
                        }
                        this.offsetY = newOffsetY;
                        this.showRanks(newOffsetY);
                        break;
    
                    default:
                        console.log(`未知消息类型:msg.action=${msg.action}`);
                        break;
                }
            });
        }
    
        fetchGroupData(shareTicket) {
            //取出群同玩成员数据
            wx.getGroupCloudStorage({
                shareTicket,
                keyList: [
                    Consts.OpenDataKeys.Grade,
                ],
                success: res => {
                    console.log("wx.getGroupCloudStorage success", res);
                    const dataLen = res.data.length;
                    this.gameDatas = dataSorter(res.data);
                    this.offsetY = 0;
                    this.maxOffsetY = dataLen * ITEM_HEIGHT;
                    if (dataLen) {
                        this.showRanks(0);
                    }
                },
                fail: res => {
                    console.log("wx.getGroupCloudStorage fail", res);
                },
            });
        }
    
        fetchFriendData() {
            //取出所有好友数据
            wx.getFriendCloudStorage({
                keyList: [
                    Consts.OpenDataKeys.Grade,
                ],
                success: res => {
                    console.log("wx.getFriendCloudStorage success", res);
                    const dataLen = res.data.length;
                    this.gameDatas = dataSorter(res.data);
                    this.offsetY = 0;
                    this.maxOffsetY = dataLen * ITEM_HEIGHT;
                    if (dataLen) {
                        this.showRanks(0);
                    }
                },
                fail: res => {
                    console.log("wx.getFriendCloudStorage fail", res);
                },
            });
        }
    
        showRanks(offsetY) {
            const startY = offsetY % ITEM_HEIGHT;
            const startIndex = Math.floor(offsetY / ITEM_HEIGHT);
            const stopIndex = startIndex + PAGE_SIZE + (startY == 0 ? 0 : 1);
            const datas = this.gameDatas.slice(startIndex, stopIndex);
    
            this.ctx.clearRect(0, 0, 1000, 1000);
            for (let i = 0, len = datas.length; i < len; i++) {
                this.drawRankItem(this.ctx, i, startIndex + i + 1, datas[i], startY, this.offsetY);
            }
        }
    
        drawAvatar(ctx, avatarUrl, x, y, w, h, cb) {
            avatarUrl = avatarUrl.substr(0, avatarUrl.lastIndexOf('/')) + "/132";
            ctx.fillStyle = "#ffffff";
            ctx.fillRect(x - 5, y - 5, w + 10, h + 10);
    
            const avatarImg = wx.createImage();
            avatarImg.src = avatarUrl;
            avatarImg.onload = () => {
                cb(avatarImg);
            };
        }
    
        //canvas原点在左上角
        drawRankItem(ctx, index, rank, data, startY, prevOffsetY) {
            const nick = data.nickname.length <= 10 ? data.nickname : data.nickname.substr(0, 10) + "...";
            const kvData = data.KVDataList.find(kvData => kvData.key === Consts.OpenDataKeys.Grade);
            const grade = kvData ? kvData.value : 0;
            const itemGapY = ITEM_HEIGHT * index - startY;
    
            //背景颜色
            if (rank % 2 == 1) {
                ctx.fillStyle = "#FBF7E4";
                ctx.fillRect(0, itemGapY, ITEM_WIDTH, ITEM_HEIGHT);
            }
    
            //名次
            if (rank < 4) {
                const rankImg = wx.createImage();
                rankImg.src = `subdomain/images/llk_phb_icon${rank}.png`;
                rankImg.onload = () => {
                    if(prevOffsetY == this.offsetY) {
                        ctx.drawImage(rankImg, 55, 30 + itemGapY, 78, 82);
                    }
                };
            } else {
                ctx.fillStyle = "#BDBDBD";
                ctx.textAlign = "right";
                ctx.baseLine = "middle";
                ctx.font = "50px Helvetica";
                ctx.fillText(`${rank}`, 100, 80 + itemGapY);
            }
    
            //头像
            const avatarX = 125;
            const avatarY = 25 + itemGapY;
            const avatarW = 80;
            const avatarH = 80;
            this.drawAvatar(ctx, data.avatarUrl, avatarX, avatarY, avatarW, avatarH, (avatarImg) => {
                if(prevOffsetY == this.offsetY) {
                    ctx.drawImage(avatarImg, avatarX, avatarY, avatarW, avatarH);
                }
            })
    
            //名字
            ctx.fillStyle = "#777063";
            ctx.textAlign = "left";
            ctx.baseLine = "middle";
            ctx.font = "30px Helvetica";
            ctx.fillText(nick, 220, 80 + itemGapY);
    
            //分数
            ctx.fillStyle = "#777063";
            ctx.textAlign = "left";
            ctx.baseLine = "middle";
            ctx.font = "30px Helvetica";
            ctx.fillText(`${grade}分`, 620, 80 + itemGapY);
        }
    }
    
    const rankList = new RankListRenderer();
    rankList.listen();
    

    上面都是在论坛上看到的,最近自己也是再写排行榜,所以整理一下,防止自己忘记

    相关文章

      网友评论

          本文标题:微信小游戏排行榜

          本文链接:https://www.haomeiwen.com/subject/qzapwftx.html