前言 / Introduction
有社区的伙伴想开发 Cocos Creator 插件,但需要学习HTML、CSS以及各种Web前端库,对游戏开发程序员真的是太难了......
社区大佬『超级浣熊』早就看穿了这一点,一直在潜心研究如何以Cocos Creator的开发方式,去开发 Cocos Creator 插件,并一直在不断实践与迭代。
近期『超级浣熊』最近研究的黑科技 SSRExtensionKit 再次刷新了我的 Cocos Creator 开发的认知:Creator + WebElement 混合开发,并以 Cocos Creator 组件化的方式使用。
首先,SSRExtensionKit 对一些基础 DOM
元素进行了封装
然后,又对基础的 css
进行了封装
同时,又对基础的 property
尝试了封装。
现在我们想一下,对于这些 DOM
元素,就使用上来说,可以大致分为两类:
独立使用的元素:
button
,a
,link
, 等等组合使用的元素:
table + tr + th
,select + option
,ul + ol + li
等等
这一节,我们来探索下,这些组合式的 DOM
元素在Cocos Creator 中的封装和使用,包含:
下拉框 / Dropdown
按钮 / Button
列表 / List
表格 / Table
下拉框 / Dropdown
首先我们来尝试一下,实现一个 下拉框
的效果,下面是用HTML元素实现的标准例子:
可以看到,下拉框的实现是通过 <select>
+ <option>
组合使用实现的。
基于我们目前为止封装的模块,这里我们有几种实现方式:
Node
添加一个SSRSelect 组件
和多个SSROption
组件Node
添加一个SSRSelect
,Node
添加多个子节点,每个子节点有一个SSROption
组件
这里选择的是第二种方式,因为这种 parent-child
的实现方式,更符合 CocosCreator 风格
。
我们参照前面几节的例子,新建两个新的元素类
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// ssr/dom/element/select.ts export class SSRElementSelect extends SSRElementCore { protected _createDOM () { this.dom = document.createElement('select'); } } // ssr/dom/element/option.ts export class SSRElementOption extends SSRElementCore { protected _createDOM () { this.dom = document.createElement('option'); } protected _addDOM () { let elementCore = this.node.parent.getComponent(SSRElementCore); if (elementCore && elementCore.dom instanceof HTMLSelectElement) { elementCore.dom.appendChild(this.dom); } else { game.container.appendChild(this.dom); } } }
可以看到 <select>
和 <option>
在代码上的差异。
其实实现方式还是很直观的:
对于 父级 元素的 <select>
和之前一样创建,没什么区别。
对于 子级 元素的 option
在创建的时候,如果 parent
具有了 select
组件,那么就添加到其节点下。
我们来使用看看。
首先是一个节点加上 select
组件。
接着为其加三个带有 option
组件的子节点:
每个子节点都有一个 innerText
的属性组件,用来为选项加上文本内容。
编辑器中预览,可以看到小小的三角形下拉框按钮,说明元素其实已经创建好了:
接着是网页中的测试:
点击下拉框后,可以看到各个选项内容:
最后是在插件系统
中的测试:
不错,看起来一切正常。
更好的事件监听 / Better Event Listener
因为下拉框总是要配合事件来使用的。
这一次,我们正好也借助这个机会,来封装并完善下事件监听的机制。
和上几节一样,暂时想要监听 下拉框选取选项事件,我们要这么写:
1
2
3this.elementSelect.dom.on('change', () => { console.log((<HTMLSelectElement>this.elementSelect.dom).selectedIndex); });
先看下效果:
可以看到,这么写,是完全没有问题的。
接着我们来想一下,是不是有办法可以让我们的 SSRElement
直接进行事件监听,而不需要再过渡到 DOM 对象呢。
答案当然是可以的,而且很简单:
1
2
3
4
5
6
7// SSRElementCore public on(type: string, callback: Function): void { HTMLElement.prototype.addEventListener.call(this.dom, ...arguments); } public off(type: string, callback: Function): void { HTMLElement.prototype.removeEventListener.call(this.dom, ...arguments); }
这样一来,我们就可以直接像 CocosCreator
中的普通 Node
对象一样,进行事件的监听了:
1
2
3this.elementSelect.on('change', (event) => { console.log((<HTMLSelectElement>this.elementSelect.dom).selectedIndex); });
我们接着来看,这里的回调函数中的 event
主要有两个问题:
获取到的对象和
SSRElementCore
没有关系用户需要自己查文档,找合适的事件名称,比如这里的
change
事件
那么我们是否可以把这种监听回调方式,也改成 CocosCreator 风格
呢,这样一来:
回调内容是 CocosCreator 风格的,自定义的内容,自然也就可以是
SSRElementCore
对象SSRElementCore
负责监听所有可能事件,提供枚举接口,用户直接挑选使用即可,这也是封装的意义所在
首先我们来看下自定义事件的实现:
1
2
3
4
5
6
7
8
9import { Event } from 'cc'; import { SSRElementCore } from './core'; export class SSRElementEvent extends Event { constructor(name: any, element?: SSRElementCore, bubbles?: boolean) { super(name, bubbles); this.element = element; } public element: SSRElementCore = null; }
接着,我们在 select
类中,注册好需要的事件:
1
2
3
4
5export class SSRElementSelect extends SSRElementCore { protected _initEventListener() { this.dom.on('change', this._onDOMEventChange.bind(this)); } }
在事件处理中,我们使用 CocosCreator 风格 来发送事件,同时附加上我们想要传递的对象:
1
2
3
4
5
6
7
8
9
10export class SSRElementSelect extends SSRElementCore { private _selectedIndex: number = -1; // ...... private _onDOMEventChange(event: Event) { this.selectedIndex = (<HTMLSelectElement>event.target).selectedIndex; this.node.dispatchEvent( new SSRElementEvent(SSRElementEventConst.OPTION_CHANGE, this) ); } }
这样修改后,我们的事件的监听就变成了:
1
2
3
4
5
6// test.ts this.elementSelect.node.on( SSRElementEventConst.OPTION_CHANGE, (event: SSRElementEvent) => { console.log((<SSRElementSelect>event.element).selectedIndex); });
测试一下:
没有任何问题。
那就趁热打铁,我们试试为 button
也用这个套路,实现一下点击事件看看:
1
2
3
4
5
6
7
8
9
10export class SSRElementButton extends SSRElementCore { protected _initEventListener() { this.dom.on('click', this._onDOMEventClick.bind(this)); } private _onDOMEventClick(event: Event) { this.node.dispatchEvent( new SSRElementEvent(SSRElementEventConst.BUTTON_CLICK, this) ); } }
这次测试的时候,我们加点难度:
在点击按钮的时候,为下拉框,动态的增加一个 option
这一切,我们完全使用 CocosCreator 风格
的代码来实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14// Test.ts this.elementButton.node.on( SSRElementEventConst.BUTTON_CLICK, (event: SSRElementEvent) => { // 创建 Node let optionNode = new Node(); // 加入 Select 所属节点 optionNode.parent = this.elementSelect.node; // SSRElementOption 组件 let elementOption = optionNode.addComponent(SSRElementOption); // SSRPropertyInnerText 组件 let propertyInnerText = optionNode.addComponent(SSRPropertyInnerText); propertyInnerText.innerText = "option4"; } );
最后来测试一下效果看看:
点击按钮后,我们就能看到动态添加的 Option
了。
当然,选中新加的 Option
的话,之前的监听函数,也会有所响应。
最后,测试一下插件中的效果:
不错,也没有任何问题。
列表 / List
有了上面的经验,我们就可以非常迅速的实现其他一些组合类型的元素,比如说有序列表,无序列表。
同样的,也是 <ul/ol> + <li>
的 parent-child
构成形式。
因此实现起来也是一样的。
表格 / Table
再来就是表格,虽然比前面的几个略微复杂,但是原理仍然是一样的 table + tr + th
。
使用 CocosCreator 风格
进行创建,再配合上合适的 css
组件:
就能制作出想要的效果:
这一节,我们主要探索了组合类型 的元素的实现方式和可能性。
同时我们还优化了 SSRElementCore
的事件机制,让它更加的贴近 CocosCreator 风格
,从而降低使用者的学习成本。
那我们下一节继续 ……
游戏开发,技术变现!本周 Cocos Store 迎来了一次历史突破,有Store开发者,一次性提取收益4.2W,代扣个人所得税超过8000元!
Cocos Store 经过一年多的发展,已经成为 Cocos 开发者们展示才华的绝佳舞台。除了收益上的回报,在这里还能收获:
技术上的成长与沉淀
志趣相投的伙伴与用户
产品商业化的认知与迭代
在这里,开发者们一路开花结果,欢迎您也来加入!
最后
以上就是单纯芝麻最近收集整理的关于超级浣熊的最近黑科技!?太有用了的全部内容,更多相关超级浣熊内容请搜索靠谱客的其他文章。
发表评论 取消回复