一、ScrollView之动态更新的优化原理
年底即将到了,工作开发任务减少了一些更多的时间是在维护和稳定性提升上;所以有些时间浏览了一下之前记录的文档,看到这篇时感觉以前记录的过于简单(虽然简单了些,但是还是留着吧,毕竟也是一部一个脚印过来的)。
然后重新阅读总结了一下并产出通用ScrollView优化功能脚本,对于ScrollView优化与原理可以参考如下链接:
CocosCreator开发笔记(5)-ScrollView之动态更新的优化原理
//之前记录的代码,相对容易理解。可以简单看看。
简版~
cc.Class({
extends: cc.Component,
properties: {
view: cc.Node,
content: cc.Node,
item: cc.Node,
},
// LIFE-CYCLE CALLBACKS:
// onLoad () {},
start () {
this.interval = 10;//item之间的间隔
this.count = Math.ceil(this.view.height / this.item.height);//单次生成
this.totalCount = 100;//总数是100个
this.content.height = (this.item.height + this.interval) * this.totalCount;
//将生成的item加入到数组中
this.items = [];
for(let i = 0; i < this.count + 1; i++){
newItem = cc.instantiate(this.item);
newItem.parent = this.content;
newItem.position = cc.v2(0,i * -(this.item.height + this.interval) - this.interval)
newItem.getChildByName("label").getComponent(cc.Label).string = i + 1;
newItem.active = true;
this.items.push(newItem);
}
//初步定义阀值
this.bufferZone = this.view.y + this.view.height / 2 + 100;
//初始化当前content的坐标
this.lastContentPosY = this.content.y;
this.updateTimer = 0;
},
// 返回item在ScrollView空间的坐标值
getPositionInView: function (item) {
let worldPos = item.parent.convertToWorldSpaceAR(item.position);
let viewPos = this.view.convertToNodeSpaceAR(worldPos);
return viewPos;
},
update (dt) {
this.updateTimer += dt;
if (this.updateTimer < 0.01) {
return; // we don't need to do the math every frame
}
this.updateTimer = 0;
let items = this.items;
// 如果当前content的y坐标小于上次记录值,则代表往下滚动,否则往上。
let isDown = this.content.y < this.lastContentPosY;
// 实际创建项占了多高(即它们的高度累加)
let offset = (this.item.height + this.interval) * items.length;
let newY = 0;
// 遍历数组,更新item的位置和显示
for (let i = 0; i < items.length; ++i) {
let viewPos = this.getPositionInView(items[i]);
if (isDown) {
// 提前计算出该item的新的y坐标
newY = items[i].y + offset;
// 如果往下滚动时item已经超出缓冲矩形,且newY未超出content上边界,
// 则更新item的坐标(即上移了一个offset的位置),同时更新item的显示内容
if (viewPos.y < -this.bufferZone && newY < 0) {
items[i].y = newY;
let id = Number(items[i].getChildByName("label").getComponent(cc.Label).string);
items[i].getChildByName("label").getComponent(cc.Label).string = id - items.length;
//更新item中的一些内容,这里我测试item下面只有一个label
}
} else {
// 提前计算出该item的新的y坐标
newY = items[i].y - offset;
// 如果往上滚动时item已经超出缓冲矩形,且newY未超出content下边界(目的是满足总数后不在进行交换),
// 则更新item的坐标(即下移了一个offset的位置),同时更新item的显示内容
if (viewPos.y > this.bufferZone && newY > -this.content.height) {
items[i].y = newY;
let id = Number(items[i].getChildByName("label").getComponent(cc.Label).string);
items[i].getChildByName("label").getComponent(cc.Label).string = id + items.length;
//更新item中的一些内容,这里我测试item下面只有一个label
}
}
}
// 更新lastContentPosY和总项数显示
this.lastContentPosY = this.content.y;
},
二、ScrollView通用脚本简述
本次总结主要产出三个尝试用的功能,简单分析一下结构:cocosCreator2.4.5
- 手动模式:数据循环更新。
- 自动模式:数据循环更新。
- 手动模式:Slider添加。
如下脚本的UML简单结构,做成通用脚本采用集成和聚合的很方便获取通用实例。
功能流程图:
1、选中ScrollVIew组件-方向二选一
2、比如竖向:对应节点从上到下或从下到上的排列方式。
3、每种排列方式有对应2种自动移动方向。
(横向和竖向换一下位置,写反了)
将脚本挂在到ScrollView组件上,然后选择ScrollView 方向,脚本中的属性会自动进行变化:
效果图:
1、slider手动模式下显示和有效,也就是不勾选isOpenAuto,并且需要手动拖入到属性中。(手动去调整slider的位置和宽高)。
2、content节点下如果没有子节点则自动根据view尺寸进行创建。(工程默认竖向11个,横向自己看一下吧)。
3、无论手动模式还是自动模式都会在这固有的节点中循环刷新。
可以直接下载gitee上的工程cocosCreator2.4.5
https://gitee.com/songhuiyuan/ScrollView.git