/**
* Created by ShawnZhang on 2017/9/8.
*/
const DEFAULT_EVENT_NAMES = [
'_onTouchStart',
'_onTouchMove',
'_onTouchEnd',
'_onTouchCancel',
];
const UIKiller = {
_prefix: '_',
_plugins: [],
registerPlugin(plugins) {
if (!Array.isArray(plugins)) {
plugins = [plugins];
}
plugins.forEach((plugin) => {
//插件能不重复
let findPlugin = this._plugins.find(item => item.name === plugin.name || item === plugin);
if (findPlugin) {
return;
}
//执行插件注册事件
this._plugins.push(plugin);
if (plugin.onRegister) {
plugin.onRegister();
}
});
},
/**
* 获取组件名字
* @param {cc.Component} component
*/
_getComponentName(component) {
return component.name.match(/<.*>$/)[0].slice(1, -1);
},
/**
* 绑定组件
* @param {cc.Component} component 要绑定的组件
* @param {Object} options 绑定选项
*/
bindComponent(component, options) {
component.$options = options || {};
let root = component.node;
root._components.forEach((nodeComponent) => {
let name = this._getComponentName(nodeComponent);
name = `$${name}`;
root[name] = nodeComponent;
});
//绑定根节点触摸事件
this._bindTouchEvent(root, component, DEFAULT_EVENT_NAMES);
//绑定所有组件子节点
this._bindNode(component.node, component);
},
/**
* 编写子节点到 target 对象
* @param node
* @param target
*/
bindNode(node, target, options) {
//初始选项
target.$options = options || {};
//检查属性收集器
if (target.$collector) {
//重复绑定,退出
if (target.$collector.node === node) {
return;
}
//更换绑定,删除之前绑定的节点
delete target.$collector.node;
//遍历收集器上的属性名,删除绑定属性
Object.keys(target.$collector).forEach((key) => {
delete target[key];
});
}
//初始化收集器
target.$collector = { node };
//遍历根节点上的组件并绑定到target
node._components.forEach((component) => {
let name = this._getComponentName(component);
name = `$${name}`;
target[name] = component;
target.$collector[name] = component;
});
//开始绑定节点
this._bindStartByPlugins(node, target);
this._bindNode(node, target);
this._bindEndByPlugins(node, target);
},
/**
* 执行插件onBindStart事件
* @param {cc.Node} node
* @param {Object} target
*/
_bindStartByPlugins(node, target) {
this._plugins.forEach((plugin) => {
if (plugin.onBindStart) {
plugin.onBindStart(node, target);
}
});
},
/**
* 执行插件onBindEnd事件
* @param {cc.Node} node
* @param {Object} target
*/
_bindEndByPlugins(node, target) {
this._plugins.forEach((plugin) => {
if (plugin.onBindEnd) {
plugin.onBindEnd(node, target);
}
});
},
/**
* 递归绑定节点
* @param {cc.Node} nodeObject
* @param {Object} target
*/
_bindNode(nodeObject, target) {
const node = nodeObject;
let isBindNode = false;
//绑定组件到自身node节点上
if (node.name[0] === this._prefix) {
node._components.forEach((component) => {
let name = this._getComponentName(component);
name = `$${name}`;
if (node[name] && target.$options.debug) {
cc.warn(`${name} property is already exists`);
return;
}
node[name] = component;
//检查组件 onBind 函数,通知组件,target 对象在绑定自己
if (UIKiller.isFunction(component.onBind)) {
component.onBind(target);
}
if (component instanceof Thor) {
//判定是否将要自行绑定的节点
if (!isBindNode && component !== target) {
isBindNode = true;
}
if (!node.active) {
component.bindHammer();
}
}
});
}
//执行插件
let bool = this._checkNodeByPlugins(node, target);
if (!bool || isBindNode) {
return;
}
node.children.forEach((child) => {
let name = child.name;
if (name[0] === this._prefix) {
let index = name.indexOf('$');
//检查控件别名
if (index !== -1) {
child.$eventName = name.substr(0, index);
child.$ = name.substr(index + 1);
name = child.$eventName + child.$[0].toUpperCase() + child.$.substr(1);
if (!CC_EDITOR) {
child.name = name;
}
}
if (target[name] && target.$options.debug) {
cc.warn(`${target.name}.${name} property is already exists`);
return;
}
this._bindTouchEvent(child, target);
target[name] = child;
//保存绑定的指针
if (target.$collector) {
target.$collector[name] = child;
}
} else if (!node[name]) {
//绑定非前缀子节点
node[name] = child;
}
this._bindNode(child, target);
});
},
/**
* 绑定触摸事件
* @param {cc.Node} node
* @param {String} event
*/
_getTouchEventName(node, event) {
let name = node.$eventName || node.name;
if (name) {
name = name[this._prefix.length].toUpperCase() + name.slice(this._prefix.length + 1);
}
if (event) {
return `_on${name}${event}`;
}
return [
`_on${name}TouchStart`,
`_on${name}TouchMove`,
`_on${name}TouchEnd`,
`_on${name}TouchCancel`,
];
},
/**
* 绑定事件
* @param {cc.Node} node
*/
_bindTouchEvent(node, target, defaultNames) {
//todo: EditBox 组件不能注册触摸事件,在原生上会导致不能被输入
if (node.getComponent(cc.EditBox)) {
return;
}
const eventNames = defaultNames || this._getTouchEventName(node);
const eventTypes = [
cc.Node.EventType.TOUCH_START,
cc.Node.EventType.TOUCH_MOVE,
cc.Node.EventType.TOUCH_END,
cc.Node.EventType.TOUCH_CANCEL,
];
eventNames.forEach((eventName, index) => {
const tempEvent = target[eventName];
if (!tempEvent && !node.getComponent(cc.Button)) {
return;
}
node.on(eventTypes[index], (event) => {
//被禁用的node 节点不响应事件
let eventNode = event.currentTarget;
if (eventNode.interactable === false || eventNode.active === false) {
return;
}
//检查button组件是否有事件处理函数,有则执行插件事件处理
const button = eventNode.getComponent(cc.Button);
if (button &&
uikiller-cocoscreator-挖洞相关.zip
需积分: 0 35 浏览量
更新于2022-11-08
收藏 760KB ZIP 举报
《Cocos Creator 2.x UI优化:新手向导与"挖洞"技术详解》
在游戏开发领域,Cocos Creator是一款广泛使用的2D和3D游戏引擎,它提供了丰富的工具和资源,使得开发者能够轻松创建游戏及交互式应用。本教程主要针对Cocos Creator 2.x版本,聚焦于UI(用户界面)的设计与优化,特别是“挖洞”技术在新手引导中的应用。
一、Cocos Creator 2.x基础与UI系统
Cocos Creator 2.x是一个跨平台的游戏开发框架,支持JavaScript和TypeScript编写代码,具有直观的可视化编辑器,便于进行图形化操作。其UI系统构建在Scene Graph之上,允许开发者通过组件化方式创建和管理界面元素,如精灵、文本、按钮等。每个UI组件都可以拥有独立的属性、事件和行为,方便自定义和复用。
二、新手引导设计
新手引导是游戏或应用中引导用户了解功能和操作流程的关键部分。在Cocos Creator中,可以通过创建序列化的场景和动画效果来实现这一目标。通过组合使用精灵、文本、按钮和动画组件,可以设计出丰富的交互式教程。此外,利用Cocos Creator的事件系统,可以监听用户的操作,适时展示相应的提示信息,确保引导的连贯性。
三、“挖洞”技术解析
“挖洞”技术,又称为UI洞洞效果,是一种常见的界面设计手法,通常用于突出显示界面中的重要元素或创建视觉焦点。在Cocos Creator中,我们可以使用遮罩层(Mask)组件来实现这一效果。遮罩层可以限制其子节点的可见区域,形成一个“洞”,露出下方的其他元素。
1. 遮罩层的创建:为需要挖洞的元素添加遮罩层组件,选择合适的形状(圆形、矩形或自定义形状),并调整大小和位置以覆盖目标区域。
2. 洞洞的形状:遮罩层的形状决定了“洞”的形状。可以使用内置的形状或者自定义精灵作为形状源,通过设置形状源的alpha通道来控制洞洞的轮廓。
3. 透明度与交互:调整遮罩层的透明度,可以实现洞洞的渐显渐隐效果,增加动态感。同时,设置好交互模式,确保被“挖洞”的元素仍然可点击或响应其他交互事件。
四、“挖洞”技术在新手引导中的应用
在新手引导中,“挖洞”技术可以用于突出关键操作区域,引导用户关注并执行特定动作。例如,当介绍某个按钮的功能时,可以通过挖洞效果让该按钮从背景中凸显出来,同时配以文字说明或动态箭头指示。用户点击后,洞洞消失,显示完整界面,完成一次交互教学。
总结,Cocos Creator 2.x提供了一套强大的UI系统,结合“挖洞”技术,开发者可以创造出引人入胜的新手引导,提升用户体验。理解并熟练运用这些技术,不仅能够使游戏或应用的界面更加美观,还能有效提高用户的参与度和留存率。在实际项目中,不断探索和实践,将这些知识点融入到自己的作品中,将有助于提升项目的整体质量。