You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
411 lines
17 KiB
411 lines
17 KiB
4 weeks ago
|
/*
|
||
|
* @Descripttion: 循环滚动容器 只支持竖向滚动或横向滚动,
|
||
|
* @version: 1.0.0
|
||
|
* @Author: YeeChan
|
||
|
* @Date: 2020-07-17 10:32:52
|
||
|
*/
|
||
|
|
||
|
import FMTouchMaskView, { SlideDirection, FMTouchEvent } from "./FMTouchMaskView";
|
||
|
import { FMListener, callFM_custom, handleFM_custom } from "../Interface/FMInterface";
|
||
|
import Utilit from "../Util/Utilit";
|
||
|
import FMItemLayout from "./FMItemLayout";
|
||
|
|
||
|
const { ccclass, property, requireComponent, disallowMultiple, menu } = cc._decorator;
|
||
|
|
||
|
@ccclass
|
||
|
// @requireComponent(cc.ScrollView)
|
||
|
@disallowMultiple() //防止多个相同类型(或子类型)的组件被添加到同一个节点
|
||
|
//@menu('FM组件/FMScrollViewLoop')
|
||
|
export default class FMScrollViewLoop extends FMTouchMaskView {
|
||
|
|
||
|
//是否自动移动
|
||
|
@property()
|
||
|
private _isAutoMoveType: boolean = true;
|
||
|
@property({ tooltip: "自动滚动", type: cc.Boolean })
|
||
|
set isAutoMoveType(val: boolean) {
|
||
|
this._isAutoMoveType = val;
|
||
|
}
|
||
|
get isAutoMoveType() { return this._isAutoMoveType; }
|
||
|
|
||
|
|
||
|
//--------------------------------------
|
||
|
//广告标签
|
||
|
protected ad_tag_custom: any;
|
||
|
//更新的回调
|
||
|
protected fmListenerUpdateData_custom: FMListener;
|
||
|
|
||
|
//layout list
|
||
|
protected arrayAliveListLayout_custom: FMItemLayout[] = []
|
||
|
//自由的节点
|
||
|
protected arrayFreeListLayout_custom: FMItemLayout[] = []
|
||
|
|
||
|
//一个屏幕中的layout数量
|
||
|
private viewLayoutNum_custom: number = 0;
|
||
|
//超出的个数
|
||
|
private viewLayoutGapNum_custom: number = 3;
|
||
|
//总共的个数
|
||
|
private viewLayoutSum_custom: number = 0;
|
||
|
|
||
|
|
||
|
//初始的下标
|
||
|
private startIndexItem_custom: number = 0;
|
||
|
//是否可以更新item相关
|
||
|
private isCanUpdateItems_custom: boolean = false;
|
||
|
//点击了 触发停止
|
||
|
private isTouchStop_custom: boolean = false;
|
||
|
//外部需要控制的是否可以update
|
||
|
private _isCanScrollViewLoopUpdate_custom: boolean = true;
|
||
|
|
||
|
|
||
|
protected isAutoMoveWayLeftUp_custom: boolean = true;//是否自动移动往左或上 还是右或下
|
||
|
//自动移动后等待的时间
|
||
|
protected autoMoveWaitTime_custom: number = 60;
|
||
|
//自动移动的一次的距离格子数量 0不启用
|
||
|
protected autoMoveWaitNum_custom: number = 1;
|
||
|
//移动的数据
|
||
|
protected autoMoveSpeed_custom: number = 3;
|
||
|
//
|
||
|
|
||
|
//当次移动的距离大小
|
||
|
private _nextMoveLength_custom: number = 0;
|
||
|
//当下需要等待的时间
|
||
|
private _waitTimeNum_custom: number = 0;
|
||
|
private _moveState_custom: number = 0;//0正常移动 1等待
|
||
|
|
||
|
|
||
|
|
||
|
protected _init_custom(): boolean {
|
||
|
if (super._init_custom()) {
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
this.viewLayoutNum_custom = Math.ceil(this.node.width / (this.itemPrefabWidth_custom));
|
||
|
} else if (this._slideDirection == SlideDirection.VERTICAL) {//垂直
|
||
|
this.viewLayoutNum_custom = Math.ceil(this.node.width / (this.itemPrefabHeight_custom));
|
||
|
}
|
||
|
//创建的个数
|
||
|
this.viewLayoutSum_custom = this.viewLayoutNum_custom + this.viewLayoutGapNum_custom * 2
|
||
|
|
||
|
let pos = 0;
|
||
|
for (let index = 0; index < this.viewLayoutSum_custom; index++) {
|
||
|
let layoutScript = this.cloneLayout_custom();
|
||
|
let layout = layoutScript.node;
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
layout.x = pos;
|
||
|
layout.y = 0;
|
||
|
pos = pos + layout.width;
|
||
|
} else if (this._slideDirection == SlideDirection.VERTICAL) {//垂直
|
||
|
layout.x = 0;
|
||
|
layout.y = pos;
|
||
|
pos = pos - layout.height
|
||
|
}
|
||
|
this.arrayAliveListLayout_custom.push(layoutScript);
|
||
|
}
|
||
|
this.isCanUpdateItems_custom = true;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 外部调用
|
||
|
* @param _listener
|
||
|
*/
|
||
|
public setFMListenerUpdateItem_custom(_listener: FMListener) {
|
||
|
this.fmListenerUpdateData_custom = _listener;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 设置自动移动的数据
|
||
|
* @param way 方向
|
||
|
* @param moveWaitNum 移动的格子 0持续
|
||
|
* @param waitTime 移动的格子后停顿的时间 s
|
||
|
* @param speed 速度
|
||
|
*/
|
||
|
public setAutoData_custom(way: number, moveWaitNum?: number, waitTime?: number, speed?: number, bgColor?: string) {
|
||
|
this.isAutoMoveWayLeftUp_custom = way == 0 ? true : false;
|
||
|
this.autoMoveWaitNum_custom = moveWaitNum ? Math.abs(moveWaitNum) : 0;
|
||
|
this.autoMoveWaitTime_custom = waitTime ? Math.abs(waitTime) * 60 : 60;
|
||
|
this.autoMoveSpeed_custom = speed ? Math.abs(speed) : 3;
|
||
|
if (bgColor) {
|
||
|
this.node.color = Utilit.colorHex2Rgb_custom(bgColor);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 是否点击了
|
||
|
*/
|
||
|
public isTouchStopView_custom() {
|
||
|
return this.isTouchStop_custom;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 外部控制是否update
|
||
|
*/
|
||
|
public setCanScrollViewLoopUpdate_custom(_update: boolean) {
|
||
|
this._isCanScrollViewLoopUpdate_custom = _update;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 设置广告的自定义标签
|
||
|
* @param tag
|
||
|
*/
|
||
|
public setAdTag_custom(tag: any) {
|
||
|
this.ad_tag_custom = tag;
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
element.setAdTag_custom(this.ad_tag_custom);
|
||
|
}
|
||
|
for (let index = 0; index < this.arrayFreeListLayout_custom.length; index++) {
|
||
|
const element = this.arrayFreeListLayout_custom[index];
|
||
|
element.setAdTag_custom(this.ad_tag_custom);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//外部初始数据
|
||
|
public initUpdateItems_custom() {
|
||
|
this._init_custom();
|
||
|
this.startIndexItem_custom = 0;
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
let pos = - this.itemPrefabWidth_custom * 3;
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
element.setPointX_custom(pos);
|
||
|
element.setItemIndex_custom(this.startIndexItem_custom + index);
|
||
|
pos = pos + this.itemPrefabWidth_custom
|
||
|
}
|
||
|
} else { //垂直
|
||
|
let pos = this.itemPrefabHeight_custom * 3;
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
element.setPointY_custom(pos);
|
||
|
element.setItemIndex_custom(this.startIndexItem_custom + index);
|
||
|
pos = pos - this.itemPrefabHeight_custom
|
||
|
}
|
||
|
}
|
||
|
this._updateNextLengthTime_custom();
|
||
|
}
|
||
|
|
||
|
protected update(dt: number): void {
|
||
|
if (this.isCanUpdateItems_custom && this._isCanScrollViewLoopUpdate_custom) {
|
||
|
this.updateScrollingItems_custom();
|
||
|
if (this.isAutoMoveType == true) {//判断类型是自动移动类型
|
||
|
this._updateAutoMove_custom();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 更新子节点的数据内容
|
||
|
* @param index 第几个大的
|
||
|
* @param childIndex 第几个小的
|
||
|
*/
|
||
|
protected listenerUpdateInitItem_custom(sum: number) {
|
||
|
if (this.fmListenerUpdateData_custom) {
|
||
|
let data = callFM_custom(this.fmListenerUpdateData_custom, sum);
|
||
|
return data;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 自动移动
|
||
|
*/
|
||
|
public _updateAutoMove_custom() {
|
||
|
if (this.isTouchStopView_custom()) {
|
||
|
return;
|
||
|
}
|
||
|
if (this._moveState_custom == 0) {
|
||
|
if (this.isAutoMoveWayLeftUp_custom) {
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
this.content_custom.x = this.content_custom.x - this.autoMoveSpeed_custom
|
||
|
} else {
|
||
|
this.content_custom.y = this.content_custom.y + this.autoMoveSpeed_custom
|
||
|
}
|
||
|
} else {
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
this.content_custom.x = this.content_custom.x + this.autoMoveSpeed_custom
|
||
|
} else {
|
||
|
this.content_custom.y = this.content_custom.y - this.autoMoveSpeed_custom
|
||
|
}
|
||
|
}
|
||
|
if (this.autoMoveWaitNum_custom > 0) {//0 持续移动
|
||
|
this._nextMoveLength_custom = this._nextMoveLength_custom - this.autoMoveSpeed_custom;
|
||
|
if (this._nextMoveLength_custom <= 0) {
|
||
|
this._moveState_custom = 1;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
this._waitTimeNum_custom = this._waitTimeNum_custom + 1;
|
||
|
if (this._waitTimeNum_custom >= this.autoMoveWaitTime_custom) {
|
||
|
this._waitTimeNum_custom = 0;
|
||
|
this._updateNextLengthTime_custom();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 消息
|
||
|
* @param event
|
||
|
*/
|
||
|
protected _dispatchEvent_custom(event: FMTouchEvent) {
|
||
|
if (event == FMTouchEvent.Scrolling) {
|
||
|
//this.updateScrollingItems();
|
||
|
} else if (event == FMTouchEvent.TouchStart) {
|
||
|
this.isTouchStop_custom = true;
|
||
|
} else if (event == FMTouchEvent.TouchEnded) {
|
||
|
this._updateNextLengthTime_custom();
|
||
|
this.isTouchStop_custom = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 更新下次移动需要的数据
|
||
|
*/
|
||
|
protected _updateNextLengthTime_custom() {
|
||
|
if (this.autoMoveWaitNum_custom > 0) {
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
this._nextMoveLength_custom = this.autoMoveWaitNum_custom * this.itemPrefab.data.width
|
||
|
if (this.isAutoMoveWayLeftUp_custom) {
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
let vcx = this.content_custom.x + element.node.x;
|
||
|
if (vcx > -element.node.width && vcx < 0) {
|
||
|
this._nextMoveLength_custom = this._nextMoveLength_custom + vcx;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (let index = this.arrayAliveListLayout_custom.length - 1; index >= 0; index--) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
let vcx = this.content_custom.x + element.node.x;
|
||
|
if (vcx < this.node.width + element.node.width && vcx > this.node.width) {
|
||
|
vcx = vcx - this.node.width;
|
||
|
this._nextMoveLength_custom = this._nextMoveLength_custom - vcx;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {//垂直
|
||
|
this._nextMoveLength_custom = this.autoMoveWaitNum_custom * this.itemPrefab.data.height
|
||
|
if (this.isAutoMoveWayLeftUp_custom) {
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
let vcy = this.content_custom.y + element.node.y;
|
||
|
if (vcy < element.node.height && vcy > 0) {
|
||
|
this._nextMoveLength_custom = this._nextMoveLength_custom - vcy;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
for (let index = this.arrayAliveListLayout_custom.length - 1; index >= 0; index--) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
let vcy = this.content_custom.y + element.node.y - element.node.height;
|
||
|
if (vcy > -(this.node.height + element.node.height) && vcy < -this.node.height) {
|
||
|
vcy = vcy + this.node.height;
|
||
|
this._nextMoveLength_custom = this._nextMoveLength_custom + vcy;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
this._waitTimeNum_custom = 0;
|
||
|
this._moveState_custom = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//更新
|
||
|
protected updateScrollingItems_custom() {
|
||
|
let arrayLive: FMItemLayout[] = []
|
||
|
if (this._slideDirection == SlideDirection.HORIZONTAL) {//水平
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
if (this.content_custom.x + element.getPointX_custom() < - this.itemPrefabWidth_custom * 3) {//左 超过三个标准 移除
|
||
|
this.addFreeItem_custom(element);
|
||
|
} else if (element.getPointX_custom() + this.content_custom.x > this.node.width + this.itemPrefabWidth_custom * 3) { //右 超过三个标准 移除
|
||
|
this.addFreeItem_custom(element);
|
||
|
} else { //中间区域 激活
|
||
|
arrayLive.push(element);
|
||
|
}
|
||
|
}
|
||
|
if (arrayLive[0].getPointX_custom() + this.content_custom.x > - this.itemPrefabWidth_custom) {//起始的 低于一个标准 创建一个
|
||
|
let element = this.getFreeItem_custom();
|
||
|
element.setPointX_custom(arrayLive[0].getPointX_custom() - this.itemPrefabWidth_custom);
|
||
|
element.setItemIndex_custom(arrayLive[0].getItemIndex_custom() - 1)
|
||
|
arrayLive.splice(0, 0, element);
|
||
|
element.node.active = true;
|
||
|
}
|
||
|
if (arrayLive[arrayLive.length - 1].getPointX_custom() + this.content_custom.x < + this.node.width + this.itemPrefabWidth_custom) {//结尾的 低于一个标准 创建一个
|
||
|
const element = this.getFreeItem_custom()
|
||
|
element.setPointX_custom(arrayLive[arrayLive.length - 1].getPointX_custom() + this.itemPrefabWidth_custom);
|
||
|
element.setItemIndex_custom(arrayLive[arrayLive.length - 1].getItemIndex_custom() + 1)
|
||
|
arrayLive.push(element);
|
||
|
element.node.active = true;
|
||
|
}
|
||
|
} else { //垂直
|
||
|
for (let index = 0; index < this.arrayAliveListLayout_custom.length; index++) {
|
||
|
const element = this.arrayAliveListLayout_custom[index];
|
||
|
if (element.getPointY_custom() + this.content_custom.y > this.itemPrefabHeight_custom * 3) {//上 超过三个标准 移除
|
||
|
this.addFreeItem_custom(element);
|
||
|
} else if (element.getPointY_custom() < -(this.content_custom.y + this.node.height + this.itemPrefabHeight_custom * 3)) { //下 超过三个标准 移除
|
||
|
this.addFreeItem_custom(element);
|
||
|
} else { //中间区域 激活
|
||
|
arrayLive.push(element);
|
||
|
}
|
||
|
}
|
||
|
if (arrayLive[0].getPointY_custom() + this.content_custom.y <= this.itemPrefabHeight_custom) {//起始的 低于一个标准 创建一个
|
||
|
let element = this.getFreeItem_custom();
|
||
|
element.setPointY_custom(arrayLive[0].getPointY_custom() + this.itemPrefabHeight_custom);
|
||
|
element.setItemIndex_custom(arrayLive[0].getItemIndex_custom() - 1)
|
||
|
arrayLive.splice(0, 0, element);
|
||
|
element.node.active = true;
|
||
|
}
|
||
|
if (arrayLive[arrayLive.length - 1].getPointY_custom() >= -(this.content_custom.y + this.node.height + this.itemPrefabHeight_custom)) {//结尾的 低于一个标准 创建一个
|
||
|
const element = this.getFreeItem_custom()
|
||
|
element.setPointY_custom(arrayLive[arrayLive.length - 1].getPointY_custom() - this.itemPrefabHeight_custom);
|
||
|
element.setItemIndex_custom(arrayLive[arrayLive.length - 1].getItemIndex_custom() + 1)
|
||
|
arrayLive.push(element);
|
||
|
element.node.active = true;
|
||
|
}
|
||
|
}
|
||
|
this.arrayAliveListLayout_custom = arrayLive;
|
||
|
}
|
||
|
/**
|
||
|
* 创建一个
|
||
|
*/
|
||
|
private cloneLayout_custom(): FMItemLayout {
|
||
|
let layout = cc.instantiate(this.itemPrefab);
|
||
|
let script = layout.getComponent(FMItemLayout);
|
||
|
script.setAdTag_custom(this.ad_tag_custom)
|
||
|
script.setFMListenerUpdate_custom(handleFM_custom(this.listenerUpdateInitItem_custom, this));
|
||
|
this.content_custom.addChild(layout);
|
||
|
return script;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 获取一个自由节点
|
||
|
*/
|
||
|
private getFreeItem_custom(): FMItemLayout {
|
||
|
let element = this.arrayFreeListLayout_custom.pop()
|
||
|
if (!element) {
|
||
|
element = this.cloneLayout_custom();
|
||
|
}
|
||
|
return element;
|
||
|
}
|
||
|
|
||
|
private addFreeItem_custom(item: FMItemLayout) {
|
||
|
item.node.active = false;
|
||
|
this.arrayFreeListLayout_custom.push(item);
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|