ListPanel.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import { _decorator, Component, Node, Prefab, EventTouch, SystemEventType, Vec3, CCBoolean, tween, EventHandler, Layout, UITransform, Label } from 'cc';
  2. import { DEV } from 'cc/env';
  3. import { GeometryUtils } from '../../core/utils/GeometryUtils';
  4. const { ccclass, property } = _decorator;
  5. @ccclass('ListPanel')
  6. export class ListPanel extends Component {
  7. @property({ type: Prefab, tooltip: "页面Item预制体" })
  8. itemPrefab: Prefab = null;
  9. @property({ type: Node, tooltip: "页面节点,触摸检测" })
  10. panelNode: Node = null;
  11. @property({ type: Node, tooltip: "页面Content节点" })
  12. panelContent: Node = null;
  13. @property({ type: Label, tooltip: "文本页签" })
  14. txtPage: Label = null;
  15. @property({ tooltip: "是否为虚拟列表" })
  16. isVirtualList: boolean = true;
  17. @property({ tooltip: "是否为循环列表" })
  18. isLoopPanel: boolean = false;
  19. // @property({
  20. // type: [Node],
  21. // tooltip: "页面子节点",
  22. // visible() { return this.isVirtualList; }
  23. // })
  24. // panelChildNodes: Node[] = [];
  25. //渲染事件(渲染器)
  26. @property({
  27. type: EventHandler,
  28. tooltip: DEV && '渲染事件(渲染器)',
  29. })
  30. public renderEvent: EventHandler = new EventHandler();
  31. private _numItems: number = 5;
  32. set numItems(val: number) {
  33. this._numItems = val;
  34. if (this.renderEvent) {
  35. for (let i = 0; i < this.panelContent.children.length; i++) {
  36. let item = this.panelContent.children[i];
  37. EventHandler.emitEvents([this.renderEvent], item, i % this._numItems);
  38. }
  39. }
  40. this.txtPage.string = `${this._index + 1}/${this._numItems}`;
  41. }
  42. get numItems() {
  43. return this._numItems;
  44. }
  45. private panelItemWidth: number = 540;
  46. private _index: number = 0;
  47. private _panelTotalIndex: number = 0;
  48. private _panelIndex: number = 0;
  49. private leftPadding = 20;
  50. private rightPadding = 20;
  51. private spacingX = 20;
  52. private get deltaMoveDis() {
  53. return this.panelItemWidth + this.spacingX;
  54. }
  55. private contentUt: UITransform;
  56. private initPoint: Vec3 = Vec3.ZERO;
  57. private startPoint: Vec3 = Vec3.ZERO;
  58. private curPoint: Vec3 = Vec3.ZERO;
  59. //private moveDis: number = 0;
  60. onLoad() {
  61. this.contentUt = this.panelContent.getComponent(UITransform);
  62. this.panelNode.on(SystemEventType.TOUCH_START, this.onTouchStart, this);
  63. }
  64. start() {
  65. this.curPoint = new Vec3(this.panelContent.position.x, this.panelContent.position.y, 0);
  66. this.panelContent.getComponent(Layout).enabled = false;
  67. this.txtPage.string = `${this._index + 1}/${this._numItems}`;
  68. }
  69. private onTouchStart(e: EventTouch) {
  70. this.initPoint = this.startPoint = GeometryUtils.V2ToV3(e.getUILocation());
  71. this.panelNode.on(SystemEventType.TOUCH_MOVE, this.onTouchMove, this);
  72. this.panelNode.on(SystemEventType.TOUCH_END, this.onTouchEnd, this);
  73. this.panelNode.on(SystemEventType.TOUCH_CANCEL, this.onTouchEnd, this);
  74. }
  75. private onTouchMove(e: EventTouch) {
  76. let touches = e.getAllTouches();
  77. if (touches.length == 1) {
  78. let point = GeometryUtils.V2ToV3(e.getUILocation());
  79. let offsetX = point.x - this.startPoint.x;
  80. this.moving(new Vec3(offsetX, 0, 0));
  81. this.startPoint = point;
  82. }
  83. }
  84. private onTouchEnd(e: EventTouch) {
  85. let point = GeometryUtils.V2ToV3(e.getUILocation());
  86. let disVec = point.subtract(this.initPoint);
  87. let dis = disVec.length();
  88. //console.log("Dis: " + disVec);
  89. if (dis > this.panelItemWidth * 0.55) {
  90. if (disVec.x <= 0) {
  91. if (this._index < this._numItems - 1 || this.isLoopPanel) {
  92. this._panelTotalIndex++;
  93. this.movePanel(true);
  94. } else {
  95. this.moveRevert();
  96. console.log("到了最右边");
  97. }
  98. } else {
  99. if (this._index > 0 || this.isLoopPanel) {
  100. this._panelTotalIndex--;
  101. this.movePanel(false);
  102. } else {
  103. this.moveRevert();
  104. console.log("到了最左边");
  105. }
  106. }
  107. } else {
  108. this.moveRevert();
  109. console.log("翻页失败");
  110. }
  111. //this.panelContent.setPosition(this.curPoint);
  112. this.startPoint = Vec3.ZERO;
  113. this.panelNode.off(SystemEventType.TOUCH_MOVE, this.onTouchMove, this);
  114. this.panelNode.off(SystemEventType.TOUCH_END, this.onTouchEnd, this);
  115. this.panelNode.off(SystemEventType.TOUCH_CANCEL, this.onTouchEnd, this);
  116. }
  117. private moveRevert() {
  118. console.log("panelPos: ", this.panelContent.position);
  119. console.log("panel init Pos: ", this.curPoint);
  120. tween(this.panelContent).to(0.15, { position: this.curPoint }).start();
  121. }
  122. private movePanel(isMoveRight: boolean) {
  123. isMoveRight ? this._index++ : this._index--;
  124. isMoveRight ? this._panelIndex++ : this._panelIndex--;
  125. if (this.isLoopPanel) {
  126. if (this._index < 0) this._index = this._numItems - 1;
  127. if (this._index > this._numItems - 1) this._index = 0;
  128. }
  129. let isRight = 0;
  130. console.log("PanelIndex: " + this._panelIndex + " Data Index: " + this._index);
  131. this._panelIndex == 2 && (isRight = 1);
  132. this._panelIndex == 0 && (isRight = -1);
  133. let targetPos = new Vec3(-this.deltaMoveDis * this._panelTotalIndex, 0, 0);
  134. //this.curPoint = targetPos;
  135. tween(this.panelContent).to(0.15, { position: targetPos }).call(() => {
  136. if (!this.isLoopPanel) { //非循环列表 会到达顶部
  137. if (isRight == 1) {
  138. if (this._index < this._numItems - 1) {
  139. let firstItem = this.panelContent.children[0];
  140. let lastPosX = this.panelContent.children[2].position.x;
  141. if (this.panelContent.children[2].position.x + this.panelItemWidth > this.contentUt.width)
  142. this.contentUt.width += this.panelItemWidth + this.spacingX;
  143. firstItem.setSiblingIndex(2);
  144. firstItem.setPosition(new Vec3(lastPosX + this.panelItemWidth + this.spacingX, 0, 0));
  145. this._panelIndex = 1;
  146. }
  147. } else if (isRight == -1) {
  148. if (this._index > 0) {
  149. let lastItem = this.panelContent.children[2];
  150. let firstPosX = this.panelContent.children[0].position.x;
  151. lastItem.setSiblingIndex(0);
  152. lastItem.setPosition(new Vec3(firstPosX - this.panelItemWidth - this.spacingX, 0, 0));
  153. this._panelIndex = 1;
  154. }
  155. }
  156. } else { //循环列表
  157. //TODO
  158. if (isRight == 1) {
  159. let firstItem = this.panelContent.children[0];
  160. let lastPosX = this.panelContent.children[2].position.x;
  161. if (this.panelContent.children[2].position.x + this.panelItemWidth > this.contentUt.width)
  162. this.contentUt.width += this.panelItemWidth + this.spacingX;
  163. firstItem.setSiblingIndex(2);
  164. firstItem.setPosition(new Vec3(lastPosX + this.panelItemWidth + this.spacingX, 0, 0));
  165. this._panelIndex = 1;
  166. } else if (isRight == -1) {
  167. let lastItem = this.panelContent.children[2];
  168. let firstPosX = this.panelContent.children[0].position.x;
  169. lastItem.setSiblingIndex(0);
  170. lastItem.setPosition(new Vec3(firstPosX - this.panelItemWidth - this.spacingX, 0, 0));
  171. this._panelIndex = 1;
  172. }
  173. }
  174. this.curPoint = targetPos;
  175. this.txtPage.string = `${this._index + 1}/${this._numItems}`;
  176. }).start();
  177. }
  178. private moving(offset: Vec3) {
  179. this.startPoint = Vec3.ZERO;
  180. offset.x *= 0.5;
  181. offset.y *= 0.5;
  182. this.panelContent.setPosition(new Vec3(this.panelContent.position.x + offset.x, this.panelContent.position.y + offset.y, 0));
  183. }
  184. private onClickLeft() {
  185. if (this._index > 0 || this.isLoopPanel) {
  186. this._panelTotalIndex--;
  187. this.movePanel(false);
  188. } else {
  189. this.moveRevert();
  190. console.log("到了最左边");
  191. }
  192. }
  193. private onClickRight() {
  194. if (this._index < this._numItems - 1 || this.isLoopPanel) {
  195. this._panelTotalIndex++;
  196. this.movePanel(true);
  197. } else {
  198. this.moveRevert();
  199. console.log("到了最右边");
  200. }
  201. }
  202. }