基本操作了解请看
在准备了知识点之后,下面来把知识点应用到具体的工程中去。
一、建立主工程 FriendsRank
如下图,我简单的建立一个helloword工程,并且修改场景,使得场景中只有一个(rank_sp) sprite作为子域描绘的地方。
二、建立子域工程
那么怎么引入子域工程呢?子域工程仅需要一个index.js 的文件即可。我先在主工程的根目录FriendsRank下建文件夹build-templates,再在build-templates下建wechatgame,再在wechatgame下建sub,然后把index.js放到sub目录下,因此获得这一一个路径FriendsRank\build-templates\wechatgame\sub\index.js。
build-templates 是构建的时候 会拷贝对应类型工程的文件到build下进行构建的,例如为当前是微信小游戏所以目录是wechatgame,还有webgame之类的。
三、主工程使用子域工程
整理好第二步后点击 “项目构建发布” 如下图,开放数据域代码目录 直接填写“sub” 即可,因为我们子域工程就是sub了。
四、开始编写主域代码 rankview.js
功能比较简单,主要都在注释里说明。
有几点比较重要 的就是
1、 子域canvas 大小需要在主域设置才有效。
2、关于updat刷新 画布,不需要随时刷。
3、主域是可以调用wx.setUserCloudStorage接口设置玩家数据的。
//因为子域跟主域代码不能互相引用,因此定义一个表,分别复制到两边当成一个来使用。
let Consts = {
OpenDataKeys: {
LevelKey: "reachlevel",
},
DomainAction: {
ShowFriendLevel: "ShowFriendLevel", //展示好友排行榜
},
}
cc.Class({
extends: cc.Component,
properties: {
mRankSprite: cc.Sprite, //这个是绑定rank_sp 的sprite,待会就在他身上把排行榜画上去。
},
onLoad () {
this.mTxt = new cc.Texture2D();
//获取子域画布
var openDataContext = wx.getOpenDataContext();
this.mOpenCanvas = openDataContext.canvas;
//标记,用来判断什么时候 能刷新this.mRankSprite.spriteFrame,一般来说排行榜不滑动的情况下刷一下就行
this.mNeedUpdataCanvas = false
},
start () {
},
update (dt) {
if (this.mNeedUpdataCanvas == true ){
//刷新this.mRankSprite.spriteFrame 和子域canvas
this.mTxt.initWithElement(this.mOpenCanvas);
this.mTxt.handleLoadedTexture();
this.mRankSprite.spriteFrame = new cc.SpriteFrame(this.mTxt);
}
},
//展示好友排行榜
showFriendsRank(){
if (this.mOpenCanvas) {
//先主动刷新一下widget大小,获得才是mRankSprite的真实大小,我这里对mRankSprite使用了widget ui组件适配屏幕变化的,如果你是固定大小则不需要刷新widget。
let widget = this.mRankSprite.getComponent(cc.Widget)
widget.updateAlignment();
//子域画布大小只能在 主域 这边 设置,我建议是先设置为mRankSprite的大小
this.mOpenCanvas.width = this.mRankSprite.node.width;
this.mOpenCanvas.height = this.mRankSprite.node.height;
//发送消息给子域通知他展示排行榜
wx.postMessage({ action: Consts.DomainAction.ShowFriendLevel, message: 'showFriendLevelRank' });
this.mNeedUpdataCanvas = true;
}
},
//点击 按钮展示排行榜
onBtnFriendsRank(){
this.showFriendsRank();
},
//点击按钮 模拟给我存10分
onBtnSaveMyLv(){
wx.setUserCloudStorage({
KVDataList:[{key:Consts.OpenDataKeys.LevelKey, value: "10" }],
success: res => {
console.log("wx.setUserCloudStorage success", res);
},
fail: res => {
console.log("wx.setUserCloudStorage fail", res);
},
})
},
});
五、编写子域代码 index.js
子域 代码编写主要请求回来的数据结构,不熟悉接口的多看文档。其他没什么注意的了。
//因为子域跟主域代码不能互相引用,因此定义一个表,分别复制到两边当成一个来使用。
let Consts = {
OpenDataKeys: {
LevelKey: "reachlevel",
},
DomainAction: {
ShowFriendLevel: "ShowFriendLevel", //展示好友排行榜
},
}
const RANK_SHOW_SIZE = 10; //展示多少条数据
const DEFAULT_LEVEL = 1;
class myRank{
constructor( ) {
this.init();
}
init(argument) {
this.canvas = wx.getSharedCanvas();
this.ctx = this.canvas.getContext('2d');
this.mDataType = null;
//数据结构
// [
// {"nickname":"name" , "openid":"openid" , "avatarUrl":"avatarUrl", "KVDataList":[ { "key":"key" ,"value":"value" } ] }
// ]
this.mBaseData = [ ];
}
//对数据进行排序处理
dealData(data) {
if (data != null) {
for (var i = data.length - 1; i >= 0; i--) {
if(data[i].KVDataList && data[i].KVDataList[0] && data[i].KVDataList[0].value){
data[i].score = parseInt(data[i].KVDataList[0].value);
}else{
data[i].score = DEFAULT_LEVEL;
}
};
let neweData = data.sort((a,b)=>{
if (a && a.score && b && b.score ) {
return a.score < b.score;
};
return false;
});
return neweData;
};
}
//开始描绘列表数据
startDrawContent(){
for (var i = 0 ; i < this.mBaseData.length ; i++) {
this.drawUnin(this.mBaseData[i] , i,100,50);
};
}
//获取好友的关卡进度
getFriendLevelList( ) {
wx.getFriendCloudStorage({
keyList: [
Consts.OpenDataKeys.LevelKey,
],
success: res => {
this.mBaseData = this.dealData(res.data);
if ( this.mBaseData ) {
this.mDataType = Consts.OpenDataKeys.LevelKey;
this.startDrawContent();
}else{
this.mDataType = null;
};
},
fail: res => {
console.log("wx.getFriendCloudStorage fail", res);
},
});
}
//描绘一个item ,item 包括 名次、头像、昵称、关卡数
drawUnin(data,index,width,height) {
var self = this
var lineHeight = 100
var HeadHeight = 80
var name = data.nickname;
var score = data.score;
var avatarUrl = data.avatarUrl;
var y = (index)*lineHeight;
var x = 20;
//使得相邻的两行背景颜色不一样
if (index%2==0) {
this.ctx.fillStyle = "#eae5e3";
}else{
this.ctx.fillStyle = "#887f7a";
};
//描绘背景
this.ctx.fillRect(0 , y , 600 , lineHeight );
this.ctx.textAlign = "center";
this.ctx.baseLine = "center";
//改变一二三名 名次字体颜色不一样
var indexFntSize = 30
if (index<=2) {
this.ctx.fillStyle = "#e0815e";
this.ctx.font = "60px Helvetica";
indexFntSize = 60
}else{
this.ctx.fillStyle = "#274a78";
this.ctx.font = "40px Helvetica";
};
//描绘名次
this.ctx.fillText(index+1, x+20, y+ indexFntSize/2+lineHeight/2 );
//描绘头像
var imgx = x + 60 + 20
const avatarImg = wx.createImage();
avatarImg.src = avatarUrl;
avatarImg.onload = () => {
self.ctx.drawImage(avatarImg, imgx , y+lineHeight/2-HeadHeight/2 , HeadHeight, HeadHeight);
};
x = imgx + HeadHeight + 100
this.ctx.fillStyle ="#165e83";
this.ctx.textAlign = "center";
this.ctx.baseLine = "center";
this.ctx.font = "30px Helvetica";
//描绘昵称
this.ctx.fillText(name, x, y+lineHeight/2 + 15 );
x = x + 40+ 100
this.ctx.fillStyle ="#ee836f";
this.ctx.font = "50px Helvetica";
//描绘关卡分数
this.ctx.fillText(score, x, y +lineHeight/2 +15 );
}
//监听主域发过来的消息
listenMainMsg(){
wx.onMessage(msg => {
switch(msg.action)
{
case Consts.DomainAction.ShowFriendLevel:
this.getFriendLevelList( );
break;
default:
console.log(`未知消息类型:msg.action=${msg.action}`);
break;
}
});
}
}
const rankList = new myRank();
//直接进行监听主域发过来的消息,做出相应的动作
rankList.listenMainMsg();
至此简简单单的排行榜功能 就有了。如果你想排行榜好看就在主域添加层修饰 rank_sp ,子域画到上面,超出去部分是会被剪裁掉的,因此可以监听rank_sp的触摸 ,实现排行榜的滑动效果。这个留到下一次再说。
欢迎线上体验
欢迎一起讨论学习。
Demo下载页面 Demo