drawcall优化 - 无限滚动容器

news/2024/9/22 13:22:16

这是一个前端项目常见的一个问题dc优化。比如一个复杂的背包容器500个元素,如果使用粗暴的实例化500个元素进去,最终的dc无疑会是灾难的。在内存管理和性能角度上讲也是铺张浪费的。

看见效果如下 dc 1091

 

但实际上500个元素itemCell,在一个屏幕视界内能看到和交互的也就6~8个。从效能上考虑,只要能无缝衔接和复用少量的元素就能满足用户需求,根本不需要填鸭式的创建并使用500个itemCell。

基于这个优化方向,做一下简单的规则设计。

 

把屏幕分成3个区块 上下红色是过渡区,用来缓冲蓝色方块的itemCell, 中间绿色是可见有效区,实时一致的显示给到用户的itemcell

我们需要做的几件事是:

1.创建少量的itemCell置于content节点下,暂定18个

2.计算并控制好滑动区域(绿色区域)itemCell的间距大小,按照滑动行程,每2行(4个itemCell)的高度进行一次更新

3.更新的操作是重绘当前的容器子节点,并同时执行ScrollView.scrollToOffset,对齐子节点位置,让用户无感的衔接到重绘后的容器布局和位置,保证观感一致

4.校验并处理滑动上下边界问题。

 

以下是演示效果 dc优化到96 (实际占用只有40左右 ,每个itemCell 占用2)

 

 

废话不多说,上代码

import { _decorator, instantiate, Label, Node, ScrollView,UITransform, Vec2 } from 'cc';
import { UIbase } from '../UIbase';
import { itemCell } from '../../../module_recovery/itemCell';
const { ccclass, property } = _decorator;@ccclass('UINotice7')
export class UINotice7 extends UIbase {@property({ type: Node, displayName: "滑动器" })private scrollNode: Node = null;@property({ type: Label, displayName: "滚动条真实y值" })private offsetLabel: Label = null;@property({ displayName: "元素数量" })private cellNum: number = 50;@property({ displayName: "无限滚动备选item数量" })private itemActualCount: number = 18;@property({ displayName: "每一页item数量" })private itemPageCount: number = 4;private scroll;//拖动窗口高度private viewHeigh = 0;private celllHeigh = 0;public static Instance: UINotice7 = null;//元素池// private cellPool: any = [];//元素下标private cellIndex = 0;//滚动条换算起点y// private transOffsetY = 0;//数据池private dataPool: any = [];//容器触底private isBottom = false;_onLoad(): void {UINotice7.Instance = this;this.node.active = false;// CMF.Instance.zIndex(this.node, UIZindex.UINotice2);this.scroll = this.scrollNode.getComponent(ScrollView)const cellNode = this.scroll.node.children[0].children[0].children[0];this.celllHeigh = cellNode.getComponent(UITransform).height;//生成数据池for (let index = 0; index < this.cellNum; index++) {this.dataPool.push(index)}console.log("初始化 this.dataPool  " + this.dataPool.length)// //动态创建阵列节点 全部// for (let index = 0; index < this.cellNum - 1; index++) {//     let insNode = instantiate(cellNode);//     insNode.setParent(this.scroll.node.children[0].children[0]);// }//动态创建 有限的阵列节点 ,n = itemActualCountfor (let index = 0; index < this.itemActualCount - 1; index++) {let insNode = instantiate(cellNode);insNode.setParent(this.scroll.node.children[0].children[0]);}this.initItemCellData()this.scroll.node.on("scrolling", this.scrolling, this);this.scroll.node.on("scroll-began", this.scrollBegan, this);// this.scroll.node.on("scroll-to-top", () => { console.log("scroll-to-top") }, this);// this.scroll.node.on("scroll-to-bottom", () => { console.log("scroll-to-bottom") }, this);this.scroll.node.on("scroll-ended", this.scrollEnd, this);this.viewHeigh = this.scroll.node.children[0].getComponent(UITransform).height;console.log("窗口可以显示 n行元素: " + this.viewHeigh / this.celllHeigh)}//初始化item数据
    initItemCellData() {let contentNode = this.scrollNode.getChildByPath("view/content");console.log("更新cell 数据下标 " + this.cellIndex)for (let index = 0; index < contentNode.children.length; index++) {let element = contentNode.children[index];if (this.dataPool.length > this.cellIndex + index) {let dataId = this.dataPool[this.cellIndex + index]let itemC = element.getComponent(itemCell);itemC.init(dataId);element.active = true;}else {element.active = false;this.isBottom = true;}}}_onDestroy(): void {UINotice7.Instance = null;}scrolling(scrollview: ScrollView, eventType, customEventData) {// let tmpPercent = 0.5 //翻页触发百分比let offsetY = this.scrollNode.getComponent(ScrollView).getScrollOffset().y;let changeHeigh = this.celllHeigh * 2let Redundant = this.viewHeigh / 2//冗余的Y空间// console.log("scrolling " + "," + offsetY_percent.toFixed(2));if (!this.isBottom && offsetY >= changeHeigh + Redundant) {//刷新,数据下标 向下翻动一页this.cellIndex += this.itemPageCount;console.log("cellIndex + ", this.itemPageCount, this.cellIndex)this.refreshContent(- changeHeigh);}else if (this.cellIndex >= this.itemPageCount && offsetY <= (Redundant - changeHeigh)) {//刷新,数据下标 向下翻动一页this.cellIndex -= this.itemPageCount;this.refreshContent(changeHeigh);this.isBottom = false;}}scrollBegan(scrollview: ScrollView, eventType, customEventData) {// this.lastoffsetY = this.scrollNode.getComponent(ScrollView).getScrollOffset().y;// console.log("scrollBegan " + "," + this.lastoffsetY);
    }scrollEnd(scrollview: ScrollView, eventType, customEventData) {let offsetY = this.scrollNode.getComponent(ScrollView).getScrollOffset().y;console.log("scrollEnd " + "," + offsetY);}protected update(dt: number): void {this.offsetLabel.string = "Y坐标 " + this.scrollNode.getComponent(ScrollView).getScrollOffset().y.toFixed(2);}//动态刷新容器阵列
    private refreshContent(toOffsetY) {toOffsetY = toOffsetY - 20if (this.cellIndex > this.dataPool.length - this.itemPageCount) {this.cellIndex = this.dataPool.length - this.itemPageCount;}if (this.cellIndex < 0)this.cellIndex = 0;console.log("动态更新阵列 元素下标" + this.cellIndex, "翻页重定位 deltaY " + toOffsetY)//动态刷新容器阵列this.initItemCellData()//更新滚动条ylet offsetY = this.scrollNode.getComponent(ScrollView).getScrollOffset().y;this.scrollNode.getComponent(ScrollView).scrollToOffset(new Vec2(0, offsetY + toOffsetY))}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/31424.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

java所有集合的相互关系是什么

Java集合框架是一个设计精良、功能强大的工具集,用于存储和操作对象集合。它大致分为以下几类,并且各类之间存在一定的层级关系和功能差异:### 顶级接口(根接口)1. **Collection**: 是最基础的集合接口,所有集合类都直接或间接实现了这个接口。它定义了基本的集合操作,如…

mysql 锁

1,介绍锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个…

Windows系统安装Jmeter教程

1、进入官网https://jmeter.apache.org/download_jmeter.cgi 选择与Jdk适配的版本下载:2、解压压缩包3、配置环境变量 进入到系统配置环境变量的界面:在下方的系统变量那里,新建变量:变量名为:JMETER_HOME 变量地址:Jmeter的安装路径 如图所示:4、运行JMETER 在JMeter的…

XeLaTeX 无法编译含有经过 pdfcrop 裁剪的 PDF 文件的文档

今天在写 LaTeX 文档时踩了个大坑,我在文档里插入了一个 PDF 图片之后文档无法编译了。 于是我去掉多余代码,做了一个最小工作示例: \documentclass{article} \usepackage{graphicx} \begin{document}\includegraphics{my_image.pdf}\end{document}就是这样一个简单的代码,…

Jenkins - [02] 安装部署

题记部分 一、Jenkins是什么Jenkins,原名Hudson,2011年改为现在的名字,它是一个开源的实现持续集成的软件工具。官网:https://www.jenkins.io/ 官网:https://www.jenkins.io/zh/ (中文)Jenkins能实时监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用图表的…

OpenTelemetry agent 对 Spring Boot 应用的影响:一次 SPI 失效的

背景 前段时间公司领导让我排查一个关于在 JDK21 环境中使用 Spring Boot 配合一个 JDK18 新增的一个 SPI(java.net.spi.InetAddressResolverProvider) 不生效的问题。 但这个不生效的前置条件有点多:JDK 的版本得在 18+ SpringBoot3.x 还在额外再配合使用 -javaagent:opentel…

easyUI datagrid 数据不显示,tablebody 高度为0 的问题

如下图,接口请求回来数据,表头也显示出来了。 打开元素,可以看到table的bbody里面是有数据的,数据也渲染到了页面表格中,但是table的height为0。 排查以下问题:检查数据源格式是否正确,如是 JSON 数组还是符合 easyui 要求的对象。确保在 datagrid 初始化后正确触发数据…

shell重定向与变量

一、重定向与管道符 重定向 重定向:改变电脑的数据输出方向,默认是输出在屏幕上类型设备文件文件描述编号默认设备标准输入 /dev/stdin 0 键盘标准输出 /dev/stdout 1 显示器标准错误输出 /dev/stderr 2 显示器交互式硬件设备标准输入:从该设备接收用户输入的数据标准输出:…