# cocoscreator-listview **Repository Path**: superfinger/cocoscreator-listview ## Basic Information - **Project Name**: cocoscreator-listview - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 3 - **Created**: 2021-07-20 - **Last Updated**: 2024-01-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Cocos Creator ScrollView优化 在游戏开发中,常常会使用`ScrollView`来实现列表的功能,如:背包、邮件列表等。但当列表的数据比较多时, 会造成界面卡顿。这是因为JS的执行是单线程的,只有完成上个任务,才能执行下一个任务。一般在`ScrollView` 加载显示对象会这样做: ```javascript for (let i = 0; i < 300; i++) { let item = this._itemPool.get()||instantiate(this.listItemPrefab) if (item){ item.parent = this.listContentNd; item.getComponent(LIstItem)?.setData(i + ""); } } ``` 使用`instantiate`克隆对象和addChild都会花费一定的时间,当要加载的数量多了,程序就会一直在执行,把一帧中渲染的时间都占用了,从而造成了界面卡顿。既然这样,我们可以把数据拆分若干的小数据集,每一帧就加载一个小数据集,这样的操作通常叫做**分帧加载**。 下面通过`lateUpdate`做一个简单的分帧加载: ```javascript lateUpdate() { if (this._isUpdating) { this.updateList(); } } private updateList() { if (this._end == this._dataSource.length) { this._listItemCount = this.listContentNd.children.length; this._isUpdating = false; return; } this._start = this._end; //每次执行30个数据 this._end = Math.min(this._end + 30, this._dataSource.length); this.renderList(this._start, this._end); this._isUpdating = true; } ``` 在使用分帧加载后,能一定程度优化体验效果。但当数据量很大的话,随着显示对象的加载和显示,会导致drawcall不断上升,从而导致帧频下降。 为了减低渲染的压力,将没有被玩家看到的元素剔除,即只渲染可以视区域的元素。 ```javascript private onScrolling() { if (this._isUpdating || this._listItemCount == 0) return; this.listContentNd.children.forEach((child: Node) => { const visible = this.checkVisible(child); child.getComponent(UIOpacity)!.opacity = visible ? 255 : 0; }); } //判断listItem是否在可视区域 private checkVisible(listItem: Node): boolean { return listItem.getComponent(UITransform)!.getBoundingBoxToWorld().intersects(this._scrollViewCollisonBox); } ``` 通过上面2个小技巧(分帧加载和只渲染可视区域的元素),能很大程度优化`ScrollView`的性能。