import { _decorator, Component, Node, Prefab, EventTouch, SystemEventType, Vec3, CCBoolean, tween, EventHandler, Layout, UITransform, Label } from 'cc'; import { DEV } from 'cc/env'; import { GeometryUtils } from '../../core/utils/GeometryUtils'; const { ccclass, property } = _decorator; @ccclass('ListPanel') export class ListPanel extends Component { @property({ type: Prefab, tooltip: "页面Item预制体" }) itemPrefab: Prefab = null; @property({ type: Node, tooltip: "页面节点,触摸检测" }) panelNode: Node = null; @property({ type: Node, tooltip: "页面Content节点" }) panelContent: Node = null; @property({ type: Label, tooltip: "文本页签" }) txtPage: Label = null; @property({ tooltip: "是否为虚拟列表" }) isVirtualList: boolean = true; @property({ tooltip: "是否为循环列表" }) isLoopPanel: boolean = false; // @property({ // type: [Node], // tooltip: "页面子节点", // visible() { return this.isVirtualList; } // }) // panelChildNodes: Node[] = []; //渲染事件(渲染器) @property({ type: EventHandler, tooltip: DEV && '渲染事件(渲染器)', }) public renderEvent: EventHandler = new EventHandler(); private _numItems: number = 5; set numItems(val: number) { this._numItems = val; if (this.renderEvent) { for (let i = 0; i < this.panelContent.children.length; i++) { let item = this.panelContent.children[i]; EventHandler.emitEvents([this.renderEvent], item, i % this._numItems); } } this.txtPage.string = `${this._index + 1}/${this._numItems}`; } get numItems() { return this._numItems; } private panelItemWidth: number = 540; private _index: number = 0; private _panelTotalIndex: number = 0; private _panelIndex: number = 0; private leftPadding = 20; private rightPadding = 20; private spacingX = 20; private get deltaMoveDis() { return this.panelItemWidth + this.spacingX; } private contentUt: UITransform; private initPoint: Vec3 = Vec3.ZERO; private startPoint: Vec3 = Vec3.ZERO; private curPoint: Vec3 = Vec3.ZERO; //private moveDis: number = 0; onLoad() { this.contentUt = this.panelContent.getComponent(UITransform); this.panelNode.on(SystemEventType.TOUCH_START, this.onTouchStart, this); } start() { this.curPoint = new Vec3(this.panelContent.position.x, this.panelContent.position.y, 0); this.panelContent.getComponent(Layout).enabled = false; this.txtPage.string = `${this._index + 1}/${this._numItems}`; } private onTouchStart(e: EventTouch) { this.initPoint = this.startPoint = GeometryUtils.V2ToV3(e.getUILocation()); this.panelNode.on(SystemEventType.TOUCH_MOVE, this.onTouchMove, this); this.panelNode.on(SystemEventType.TOUCH_END, this.onTouchEnd, this); this.panelNode.on(SystemEventType.TOUCH_CANCEL, this.onTouchEnd, this); } private onTouchMove(e: EventTouch) { let touches = e.getAllTouches(); if (touches.length == 1) { let point = GeometryUtils.V2ToV3(e.getUILocation()); let offsetX = point.x - this.startPoint.x; this.moving(new Vec3(offsetX, 0, 0)); this.startPoint = point; } } private onTouchEnd(e: EventTouch) { let point = GeometryUtils.V2ToV3(e.getUILocation()); let disVec = point.subtract(this.initPoint); let dis = disVec.length(); //console.log("Dis: " + disVec); if (dis > this.panelItemWidth * 0.55) { if (disVec.x <= 0) { if (this._index < this._numItems - 1 || this.isLoopPanel) { this._panelTotalIndex++; this.movePanel(true); } else { this.moveRevert(); console.log("到了最右边"); } } else { if (this._index > 0 || this.isLoopPanel) { this._panelTotalIndex--; this.movePanel(false); } else { this.moveRevert(); console.log("到了最左边"); } } } else { this.moveRevert(); console.log("翻页失败"); } //this.panelContent.setPosition(this.curPoint); this.startPoint = Vec3.ZERO; this.panelNode.off(SystemEventType.TOUCH_MOVE, this.onTouchMove, this); this.panelNode.off(SystemEventType.TOUCH_END, this.onTouchEnd, this); this.panelNode.off(SystemEventType.TOUCH_CANCEL, this.onTouchEnd, this); } private moveRevert() { console.log("panelPos: ", this.panelContent.position); console.log("panel init Pos: ", this.curPoint); tween(this.panelContent).to(0.15, { position: this.curPoint }).start(); } private movePanel(isMoveRight: boolean) { isMoveRight ? this._index++ : this._index--; isMoveRight ? this._panelIndex++ : this._panelIndex--; if (this.isLoopPanel) { if (this._index < 0) this._index = this._numItems - 1; if (this._index > this._numItems - 1) this._index = 0; } let isRight = 0; console.log("PanelIndex: " + this._panelIndex + " Data Index: " + this._index); this._panelIndex == 2 && (isRight = 1); this._panelIndex == 0 && (isRight = -1); let targetPos = new Vec3(-this.deltaMoveDis * this._panelTotalIndex, 0, 0); //this.curPoint = targetPos; tween(this.panelContent).to(0.15, { position: targetPos }).call(() => { if (!this.isLoopPanel) { //非循环列表 会到达顶部 if (isRight == 1) { if (this._index < this._numItems - 1) { let firstItem = this.panelContent.children[0]; let lastPosX = this.panelContent.children[2].position.x; if (this.panelContent.children[2].position.x + this.panelItemWidth > this.contentUt.width) this.contentUt.width += this.panelItemWidth + this.spacingX; firstItem.setSiblingIndex(2); firstItem.setPosition(new Vec3(lastPosX + this.panelItemWidth + this.spacingX, 0, 0)); this._panelIndex = 1; } } else if (isRight == -1) { if (this._index > 0) { let lastItem = this.panelContent.children[2]; let firstPosX = this.panelContent.children[0].position.x; lastItem.setSiblingIndex(0); lastItem.setPosition(new Vec3(firstPosX - this.panelItemWidth - this.spacingX, 0, 0)); this._panelIndex = 1; } } } else { //循环列表 //TODO if (isRight == 1) { let firstItem = this.panelContent.children[0]; let lastPosX = this.panelContent.children[2].position.x; if (this.panelContent.children[2].position.x + this.panelItemWidth > this.contentUt.width) this.contentUt.width += this.panelItemWidth + this.spacingX; firstItem.setSiblingIndex(2); firstItem.setPosition(new Vec3(lastPosX + this.panelItemWidth + this.spacingX, 0, 0)); this._panelIndex = 1; } else if (isRight == -1) { let lastItem = this.panelContent.children[2]; let firstPosX = this.panelContent.children[0].position.x; lastItem.setSiblingIndex(0); lastItem.setPosition(new Vec3(firstPosX - this.panelItemWidth - this.spacingX, 0, 0)); this._panelIndex = 1; } } this.curPoint = targetPos; this.txtPage.string = `${this._index + 1}/${this._numItems}`; }).start(); } private moving(offset: Vec3) { this.startPoint = Vec3.ZERO; offset.x *= 0.5; offset.y *= 0.5; this.panelContent.setPosition(new Vec3(this.panelContent.position.x + offset.x, this.panelContent.position.y + offset.y, 0)); } private onClickLeft() { if (this._index > 0 || this.isLoopPanel) { this._panelTotalIndex--; this.movePanel(false); } else { this.moveRevert(); console.log("到了最左边"); } } private onClickRight() { if (this._index < this._numItems - 1 || this.isLoopPanel) { this._panelTotalIndex++; this.movePanel(true); } else { this.moveRevert(); console.log("到了最右边"); } } }