微信子域控制
版本支持
Cocos Creator ver: >= 2.0
功能说明
wxRender 组件为微信子域内容的显示隐藏做自动化处理,主域代码只需要使用 showPanel 与 hidePanel 来显示界面,不需要关注子域层级及暂停恢复问题。
使用说明
-
在 Canvas 节点下最下方添加空节点节点,下称 wxRender 节点
-
设置 wxRender 节点尺寸比例与微信微信子域项目的尺寸比例一致,推荐使用 1:1 的比例,方便主域与子域位置对齐。该节点的位置即子域渲染的位置。
-
在 wxRender 节点上添加
Component/wxRender
组件。 继续在在组件的属性上配置子域界面名,注意界面名称需要与主域对应界面名一致。如下图所示: -
设置子域内容,子域框架与主域一致。设置子域 Canvas 的属性,将设计分辨率(Design Resolution)设置成与主域 wxRender 节点比例一致(推荐 1:1)
-
在子域代码中添加事件监听与事件注册
// 子域监听主域发送的消息,需要区分 Cocos creator 引擎发送的消息,网络消息,事件消息
wx.onMessage(function(data) {
console.log("wx shared receive msg:" + JSON.stringify(data));
var msg = data["msg"];
var eventName = data["event"];
if (data.event === 'viewport') { // cocos creator 事件
const { width, height } = data;
} else if (msg) {
// 当作网络消息来处理
network.dispatch(msg, data["param"]);
} else {
// 当作客户端事件来处理
var args = data["param"];
args.unshift(eventName);
clientEvent.dispatchEvent(...args);
}
});
// 设置游戏帧率
clientEvent.on('frameRate', (frameRate) => {
cc.info('frameRate: ', frameRate);
if (frameRate < 1) {
cc.game.pause();
} else {
if (cc.game.isPaused()) {
cc.game.resume();
}
cc.game.setFrameRate(frameRate);
}
});
// 剩下的可以自行定义监听事件
特殊情况处理
提升子域帧率
默认子域游戏帧率为 10 帧,在需要子域显示动画(如排行榜滑动)时,需要手动提升游戏帧率。 在需要提高帧率的界面展示前派发如下事件
clientEvent.dispatchEvent('wxSubPanelStart', 30);
即可。当前界面关闭后会自动降低子域帧率,不用再进行操作。
主域与子域界面名称不一致(请不要这样做,只是为了兼容)
在一个项目中需要兼容不同的框架,而不进行较大的改动。如果不在一个场景中需要添加 sceneFactory 组件到 Canvas 下,添加 layout、uiroot节点,将框架添加到新场景中。 再通过实践派发进行手动触发,注意这里的子域界面显示与隐藏需要手动触发
clientEvent.dispatchEvent('wxSubPanelStart', 10);
clientEvent.dispatchEvent('dispatchWxEvent', 'showPanel', 'revivePanel', PlayerManager.player.maxFansCnt);
clientEvent.dispatchEvent('dispatchWxEvent', 'hidePanel', 'revivePanel');
clientEvent.dispatchEvent('wxSubPanelStop');
实现方法
思路
在游戏框架中显示与隐藏界面需要使用 showPanel
与 hidePanel
, 在 框架处理事件完成后会发送 showPanelOver
或 hidePanelOver
. 这时在 Component/wxRender
组件中需要对这两个事件进行监听.
- 判断显示的界面是否有在子域中显示的内容,如果有就向子域派发对应的显示命令,如果没有就关闭子域渲染.
- 判断隐藏的界面有没有子域内容,如果有就向子域发送对应的隐藏命令,否则什么都不做
实现
- 监听
panelCenter
中发送过来的 showPanelOver 与 hidePanelOver, 在 showPanelOver 中可以进行数据的透传,子域界面显示内容的参数由这里获取.
// 监听界面显示完成
// 需要对界面进行判断,只对模态框类型的界面进行处理. 其他如提示框或 ui 不进行处理.
clientEvent.on('showPanelOver', (newPanelName, ...param) => {
for (const panel of this.panelCenter.subPanelStack) {
if (panel.name === newPanelName) {
const len = this.panelCenter.subPanelStack.length;
const oldPanel = this.panelCenter.subPanelStack[len - 2];
this.onPanelChange(oldPanel ? oldPanel.name : '', newPanelName, param);
}
}
});
// 监听界面隐藏完成
// 隐藏界面因为已经不在 this.panelCenter.subPanelStack 数组中,不能判断是否为模态框.但是对隐藏的界面只需要判断是否由子域界面要进行隐藏,所以是不是模态框并没有什么影响
clientEvent.on('hidePanelOver', (oldPanelName) => {
const len = this.panelCenter.subPanelStack.length;
const newPanel = this.panelCenter.subPanelStack[len - 1];
this.onPanelChange(oldPanelName, newPanel ? newPanel.name : '');
});
- 处理显示隐藏的逻辑.在发送显示与隐藏子域的信息时,同时对子域的显示,停止做出判断.
onPanelChange (oldPanelName, newPanelName, param) {
console.log('onPanelChange: ', oldPanelName, newPanelName);
if (this.wxPanelName.indexOf(oldPanelName) !== -1) { // 旧界面有子域
this.sendToWxSubContent('hidePanel', [oldPanelName]);
}
if (newPanelName) {
if (this.wxPanelName.indexOf(newPanelName) !== -1) { // 新界面有子域
let args = [];
if (param) {
args = [newPanelName, ...param];
} else {
args = [newPanelName];
}
this.sendToWxSubContent('showPanel', args);
this.wxSubPanelStart(this.curFrameRate);
} else {
this.wxSubPanelStop();
}
}
},