参考https://blog.csdn.net/juedno/article/details/81775599
// Learn cc.Class:
// - https://docs.cocos.com/creator/manual/en/scripting/class.html
// Learn Attribute:
// - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
cc.Class({
extends: cc.Component,
properties: {
// foo: {
// // ATTRIBUTES:
// default: null, // The default value will be used only when the component attaching
// // to a node for the first time
// type: cc.SpriteFrame, // optional, default is typeof default
// serializable: true, // optional, default is true
// },
// bar: {
// get () {
// return this._bar;
// },
// set (value) {
// this._bar = value;
// }
// },
item: cc.Prefab,
Scroll: cc.ScrollView,
//显示用的content
content: cc.Node,
//附加mask组件的对象
maskNode: cc.Node,
//方向,0是垂直方向,1是水平方向
dir: 0,
isVertical: true,
},
// LIFE-CYCLE CALLBACKS:
onLoad() {
this.itemsList = new Array();
this.num = 30;
this.itemNum = 3;
//滑动的方向
this.distance = 300;//item之间的间距
this.needSize = 0;//需求要求的高度/宽度
this.visibleHeight = 0;//显示范围高度
this.itemsHeight = 0;//物品高度
this.OnScrollFun = null;//滑动回调
//可见范围
this.minY = 0;
this.maxY = 0;
//可以显示的范围,可见范围 超过 可以显示的范围,就刷新列表(把缓存的item放到下面或上面)
this.minVisibleY = 0;
this.maxVisibleY = 0;
this.initX = this.distance / 2;
this.initY = -this.distance / 2;
this.miniIdx = 0;
this.maxIdx = 0;
this.curOffset = 0;
this.startY = this.content.y;
},
start() {
this.Init(this.itemNum);
},
Init(num) {
/*
var eventHandler = new cc.Component.EventHandler();
eventHandler.target = this.node;
eventHandler.component = "ScrollHelper";
eventHandler.handler = "OnScroll";
this.Scroll.scrollEvents.push(eventHandler);*/
this.needSize = this.num * this.distance;
if (!this.isVertical) {
this.initX = this.distance / 2;
this.initY = 0;
this.content.setContentSize(new cc.Size(this.needSize, this.content.getContentSize().height));
} else {
this.initX = 0;
this.initY = -this.distance / 2;
this.content.setContentSize(new cc.Size(this.content.getContentSize().width, this.needSize));
}
this.visibleHeight = this.maskNode.getContentSize().height;
this.InitObjs();
},
InitObjs() {
let curX = 0;
let curY = 0;
for (let i = 0; i < this.itemNum; i++) {
let obj = cc.instantiate(this.item);
obj.parent = this.content;
//this.node.getComponent("CollectPanel").setPic(i, obj);
obj.active = true;
if (!this.isVertical) {
curX = this.initX + this.distance * i;
// console.error("curX:" + curX);
}
else {
curY = this.initY - this.distance * i;
// console.error("curY:" + curY);
}
obj.setPosition(cc.v2(curX, curY));
this.onRefresh(obj, i, i);
this.itemsList.push(obj);
}
},
//计算边界,超过边界则刷新列表
//offest是左上角原点滑动的偏移量
countBorder(offest) {
let height = this.visibleHeight;//可见高度
this.minY = offest;//获得相对于左上角原点的最小y值
this.maxY = offest + height;//获得相对于左上角原点的最大y值
},
OnScroll() {
//获取滚动视图相对于左上角原点的当前滚动偏移
let scrollOffset = this.Scroll.getScrollOffset();
let offest = 0;
if (!this.isVertical)
//水平的offset是负数,为什么会有这么sb的设计,将它取反和垂直方向的统一一下
offest = -scrollOffset.x;
else
offest = this.content.y;
this.curOffset = offest;
this.refresh();
},
//强行刷新
refresh() {
let offest = this.curOffset;
//最大高度,超过该高度,不刷新
let maxY = this.needSize;
if (offest < 0 || offest + this.visibleHeight >= maxY)
return;
let idx = 0;//从0开始
this.countBorder(offest);
// return;
this.oldIndex = this.miniIdx;
this.miniIdx = Math.floor(offest / this.distance);
if (this.oldIndex === this.miniIdx) {
return;
}
//cc.log(this.oldIndex, this.miniIdx);
//cc.log(this.miniIdx)
// console.error("this.miniIdx:" + this.miniIdx);
this.minVisibleY = this.miniIdx * this.distance;
this.maxVisibleY = this.maxIdx * this.distance;
//miniIdx到maxIdx都会刷新
for (let i = 0; i < this.itemNum; i++) {
let obj = this.itemsList[i];
idx = this.miniIdx + i;
this.refreshItem(idx, i, obj);
}
this.maxIdx = this.miniIdx + this.itemNum;
},
//idx是UI该刷新的第几个元素
refreshItem(idx, objIdx, obj) {
if (idx < 0 || idx >= this.num)
return;
if (obj == null) {
console.error("obj为空!");
return;
}
let curX = 0;
let curY = 0;
if (!this.isVertical)
curX = this.initX + this.distance * idx;
else
curY = this.initY - this.distance * idx;
// console.error("idx:" + idx + ",curX:" + curX + ",curY:" + curY);
obj.setPosition(cc.v2(curX, curY));
//obj.setPositionX(curX);
//obj.setPositionY(curY);
this.onRefresh(obj, idx, objIdx);
},
/**
* 刷新回调
* @param obj
* @param idx 需求显示的索引
* @param objIdx 实际的item索引
*/
onRefresh(obj, idx, objIdx) {
//测试用
//let label = cc.find("text", obj).getComponent(cc.Label);
//label.string = idx;
//if (this.OnScrollFun)
// this.OnScrollFun(obj, idx, objIdx);
//cc.log(idx, objIdx)
idx = parseInt(idx);
this.node.getComponent("CollectPanel").setPic(idx, objIdx);
},
});