UI 虚拟化实现细节。如何实施?
UI virtualization implementation details. How to implement it?
我知道有几个框架实现了 UI 虚拟化,例如 C# WPF、Qt QML 和 Aurelia JS。
我了解了虚拟化的工作原理以及滚动期间项目如何回收的基本概念。
鉴于我很难理解:
- 给定偏移量,视口如何知道需要绘制哪个项目?
- 如果项目可以有不同的高度,视口如何计算它的实际尺寸?
真正的问题是在滚动期间绘制的项目中的可变高度(或宽度)。事实上,如果绘制控件的高度是固定的,一切都很简单:
- 内容大小为 numItems*itemHeight(或 numItems * itemWidth)
- 视图中绘制的第一个项目由 ViewPortOffset / ItemHeight 计算。例如,如果视口的大小为 100x100,当前偏移量为 200,itemHeight 为 10,则第一个要绘制的项目为项目 20。
是否有任何类型的资源或博客可用于学习如何使用变量解决此问题 heights/widths
我相信大多数 UI 虚拟化都依赖于具有相同大小的项目。
如果您需要您的对象具有不可预测的大小,那么我想到了一个想法。对于每个元素存储某处它开始的偏移量(px 位置)。我认为最好的是一系列职位。
例如,您有 10 个大小为 10x10、20x20、...、100x100 的对象的垂直视图。它们将从以下位置开始:0, 10, 30, 60, ...
假设您的视图当前显示范围是 y1 = 15
到 y2 = 40
。现在您需要渲染所有从大于 y1
且小于 y2
的位置开始的对象,并且从每一侧再渲染一个对象。所以你需要渲染第二个、第三个和第四个对象。
当然,如何存储起始位置以及使用什么算法来查找值非常重要。如果您需要视图包含很多项目,那么您还应该考虑实现算法所用的语言。
在我的 Sciter Engine 中,我有一个具有可变高度的虚拟可滚动项目列表的示例:
有或没有动力(动画)滚动支持。
实现非常简单,查看 {sciter-sdk}/samples/ideas/virtual-list/vertical.htm 演示和 tapev.tis implementation.
它使用 DOM 个元素的滑动但固定的缓冲区 - 在任何给定的时刻,只有 const BUFFER_SIZE = 20;
个元素被加载到视图中。因此它可以用来滚动无限长度的记录集。
它工作得很好,但有一个明显的限制——没有滚动条。准确地说:没有反映 items/content 维度的滚动条,因为整个记录集在呈现时不可用。但是你可以有近似于那个的滚动条 - 例如滚动条滑块大小反映了看到的项目数及其位置 - 视图中第一个项目的索引。
我知道有几个框架实现了 UI 虚拟化,例如 C# WPF、Qt QML 和 Aurelia JS。
我了解了虚拟化的工作原理以及滚动期间项目如何回收的基本概念。
鉴于我很难理解:
- 给定偏移量,视口如何知道需要绘制哪个项目?
- 如果项目可以有不同的高度,视口如何计算它的实际尺寸?
真正的问题是在滚动期间绘制的项目中的可变高度(或宽度)。事实上,如果绘制控件的高度是固定的,一切都很简单:
- 内容大小为 numItems*itemHeight(或 numItems * itemWidth)
- 视图中绘制的第一个项目由 ViewPortOffset / ItemHeight 计算。例如,如果视口的大小为 100x100,当前偏移量为 200,itemHeight 为 10,则第一个要绘制的项目为项目 20。
是否有任何类型的资源或博客可用于学习如何使用变量解决此问题 heights/widths
我相信大多数 UI 虚拟化都依赖于具有相同大小的项目。
如果您需要您的对象具有不可预测的大小,那么我想到了一个想法。对于每个元素存储某处它开始的偏移量(px 位置)。我认为最好的是一系列职位。
例如,您有 10 个大小为 10x10、20x20、...、100x100 的对象的垂直视图。它们将从以下位置开始:0, 10, 30, 60, ...
假设您的视图当前显示范围是 y1 = 15
到 y2 = 40
。现在您需要渲染所有从大于 y1
且小于 y2
的位置开始的对象,并且从每一侧再渲染一个对象。所以你需要渲染第二个、第三个和第四个对象。
当然,如何存储起始位置以及使用什么算法来查找值非常重要。如果您需要视图包含很多项目,那么您还应该考虑实现算法所用的语言。
在我的 Sciter Engine 中,我有一个具有可变高度的虚拟可滚动项目列表的示例:
有或没有动力(动画)滚动支持。
实现非常简单,查看 {sciter-sdk}/samples/ideas/virtual-list/vertical.htm 演示和 tapev.tis implementation.
它使用 DOM 个元素的滑动但固定的缓冲区 - 在任何给定的时刻,只有 const BUFFER_SIZE = 20;
个元素被加载到视图中。因此它可以用来滚动无限长度的记录集。
它工作得很好,但有一个明显的限制——没有滚动条。准确地说:没有反映 items/content 维度的滚动条,因为整个记录集在呈现时不可用。但是你可以有近似于那个的滚动条 - 例如滚动条滑块大小反映了看到的项目数及其位置 - 视图中第一个项目的索引。