GListView.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. let isSimilarEqualWithNumber = function (a, b) {
  2. if (Math.abs(a - b) < 0.005) {
  3. return true;
  4. }
  5. return false
  6. }
  7. cc.Class({
  8. extends: cc.Component,
  9. properties: {
  10. itemTemplate:
  11. {
  12. default: null,
  13. type: cc.Node
  14. },
  15. scriptName: '',
  16. },
  17. // use this for initialization
  18. onLoad: function () {
  19. this.direction = this.node.getComponent("cc.ScrollView").horizontal ? 1 : 0;
  20. this.contentView = cc.find("view/content", this.node);
  21. // this.contentView.anchorY = 1;
  22. // this.contentView.anchorX = 0;
  23. // this.contentView.x = -this.node.width / 2;
  24. // this.contentView.y = this.node.height / 2;
  25. this._needUpdate = true; // 判断是否要调用update函数
  26. this._dataprovider = null;
  27. this._offset = null;
  28. this.itemList = [];
  29. this.itemTemplate.active = false;
  30. // 测试 begin
  31. let list = [];
  32. let k = 80;
  33. while (k > 0) {
  34. list.push(k);
  35. k--;
  36. }
  37. this.setDataProvider(list, 11);
  38. // 测试 end
  39. },
  40. /**
  41. * 设置数据源
  42. * firstShowIndex 第一个显示的索引
  43. **/
  44. setDataProvider: function (list, firstShowIndex) {
  45. this.itemList.forEach(function (element) { element.parent = null; });
  46. this.itemList = [];
  47. if (list.length < 1) {
  48. this.contentView.width = this.node.width;
  49. this.contentView.height = this.node.height;
  50. this._needUpdate = false;
  51. return;
  52. }
  53. let contentWidth = this.itemTemplate.width;
  54. let contentHeight = this.itemTemplate.height;
  55. let itemNum = 0;
  56. if (this.direction === 0) {
  57. contentHeight = list.length * contentHeight;
  58. if (contentHeight < this.node.height) {
  59. contentHeight = this.node.height;
  60. this._needUpdate = false;
  61. itemNum = list.length;
  62. } else {
  63. itemNum = Math.ceil(this.node.height / this.itemTemplate.height) + 2;
  64. }
  65. } else {
  66. contentWidth = list.length * contentWidth;
  67. if (contentWidth < this.node.width) {
  68. contentWidth = this.node.width;
  69. this._needUpdate = false;
  70. itemNum = list.length;
  71. } else {
  72. itemNum = Math.ceil(this.node.width / this.itemTemplate.width) + 2;
  73. }
  74. }
  75. itemNum = itemNum > list.length ? list.length : itemNum;
  76. this.contentView.width = contentWidth;
  77. this.contentView.height = contentHeight;
  78. this._dataprovider = [];
  79. list.forEach(function (data, index) {
  80. let obj = {};
  81. obj.data = data;
  82. if (this.direction === 0) {
  83. obj.x = this.itemTemplate.x;
  84. obj.y = -this.itemTemplate.height * index;
  85. } else {
  86. obj.x = this.itemTemplate.width * index;
  87. obj.y = this.itemTemplate.y;
  88. }
  89. this._dataprovider.push(obj);
  90. }.bind(this));
  91. // 预先创建多个可用的ItemRenderer
  92. // cc.log(`创建${itemNum}个ItemRenderer`);
  93. // cc.log(`dataprovider `,this._dataprovider)
  94. while (itemNum > 0) {
  95. let itemRenderer = cc.instantiate(this.itemTemplate);
  96. itemRenderer.parent = this.contentView;
  97. itemRenderer.active = true;
  98. this.itemList.push(itemRenderer);
  99. --itemNum;
  100. }
  101. itemNum = this.itemList.length;
  102. firstShowIndex = firstShowIndex || 0;
  103. if (firstShowIndex > (this._dataprovider.length - itemNum)) {
  104. firstShowIndex = this._dataprovider.length - itemNum - 1;
  105. }
  106. if (!this._needUpdate) {
  107. firstShowIndex = 0;
  108. }
  109. for (let i = 0; i < itemNum; i++) {
  110. this.itemList[i].x = this._dataprovider[i + firstShowIndex].x;
  111. this.itemList[i].y = this._dataprovider[i + firstShowIndex].y;
  112. this.setItemData(this.itemList[i], i + firstShowIndex);
  113. // cc.log("this.itemList.x" + i,this.itemList[i].x )
  114. }
  115. let contentPos = this.node.getComponent("cc.ScrollView").getContentPosition();
  116. if (this.direction === 0) {
  117. contentPos.y = this.node.height / 2 + firstShowIndex * this.itemTemplate.height;
  118. this.node.getComponent("cc.ScrollView").setContentPosition(contentPos)
  119. } else {
  120. contentPos.x = -this.node.width / 2 - firstShowIndex * this.itemTemplate.width;
  121. this.node.getComponent("cc.ScrollView").setContentPosition(contentPos)
  122. }
  123. this._offset = this.node.getComponent("cc.ScrollView").getScrollOffset();
  124. },
  125. // called every frame, uncomment this function to activate update callback
  126. update: function (dt) {
  127. if (!this._needUpdate) { return; }
  128. let offset = this.node.getComponent("cc.ScrollView").getScrollOffset();
  129. let num = this.itemList.length;
  130. if (this.direction === 0) {
  131. if (offset.y < 0) {
  132. return;
  133. }
  134. // cc.log("offset",offset);
  135. let _dOffsety = offset.y - this._offset.y;
  136. if (_dOffsety > 0) {
  137. let itemNode = this.itemList[0];
  138. let _y = itemNode.y + offset.y;
  139. if (_y > itemNode.height * 2) {
  140. // 只移动最上层的itemNode
  141. itemNode.y = this.itemList[num - 1].y - itemNode.height;
  142. this.itemList.shift();
  143. this.itemList.push(itemNode);
  144. this.setItemData(itemNode, itemNode["$index"] + num);
  145. }
  146. } else if (_dOffsety < 0) {
  147. let itemNode = this.itemList[num - 1];
  148. let _dy = -itemNode.y - (this.node.height + offset.y);
  149. if (_dy > itemNode.height) {
  150. itemNode.y = this.itemList[0].y + itemNode.height;
  151. this.itemList.pop();
  152. this.itemList.unshift(itemNode);
  153. this.setItemData(itemNode, itemNode["$index"] - num);
  154. }
  155. }
  156. } else {
  157. if (offset.x > 0) {
  158. return;
  159. }
  160. // cc.log("offset",offset.x)
  161. if (this._offset.x > offset.x) // 向左滚动
  162. {
  163. let itemNode = this.itemList[0];
  164. let _x = itemNode.x + offset.x;
  165. // cc.log("向左滚动",_x)
  166. if (_x < -itemNode.width * 2) {
  167. itemNode.x = this.itemList[num - 1].x + itemNode.width;
  168. this.itemList.shift()
  169. this.itemList.push(itemNode);
  170. this.setItemData(itemNode, itemNode["$index"] + num);
  171. }
  172. } else if (this._offset.x < offset.x) // 向右滚动
  173. {
  174. let itemNode = this.itemList[num - 1];
  175. let _x = itemNode.x + offset.x;
  176. // cc.log("向右滚动",_x)
  177. if (_x > (this.node.width + itemNode.width)) {
  178. itemNode.x = this.itemList[0].x - itemNode.width
  179. this.itemList.pop();
  180. this.itemList.unshift(itemNode);
  181. this.setItemData(itemNode, itemNode["$index"] - num)
  182. }
  183. }
  184. }
  185. this._offset = offset;
  186. },
  187. onDestroy: function () {
  188. this.itemList = null;
  189. this._dataprovider = null;
  190. this._offset = null;
  191. this.contentView = null;
  192. },
  193. // 自己去扩展该方法吧
  194. setItemData: function (itemNode, index) {
  195. itemNode["$index"] = index;
  196. itemNode.active = (index >= 0 && index < this._dataprovider.length);
  197. // itemNode.getComponentInChildren("cc.Label").string = "h-" + index;
  198. itemNode.getComponent(this.scriptName).updateItem(null, index);
  199. // cc.log(`itemNode["$index"] ${index}`);
  200. }
  201. });