高性能多维分析表格实现原理剖析

VTable 是 VisActor 可视化体系中的表格组件库,基于可视化渲染引擎 VRender 进行封装。 VTable 以其优异的性能表现,丰富的可视化能力,迅速得到大量用户的认可。同时也有大批开发者对其实现原理感兴趣,我们将撰写一系列文章来进行详细介绍。

本篇文章介绍一下VTable的架构设计和底层实现。

模块简介

Options

Options 是用户传入的表格配置,用来描述表格的结构、内容和样式。Options中主要有以下几类配置:

  • 列表配置:列表的表头配置,转置配置,以及列(行)对应的单元格类型等
  • 透视表配置:透视表行列表头配置,指标所在位置,以及指标对应的单元格类型等
  • 表格宽高相关配置:表格长宽方向的显示模式(依内容自动宽高、适应容器等),表格的默认宽高等
  • 表格状态相关配置:表格的冻结、排序等状态
  • 表格组件相关配置:表格的标题、菜单、滚动条等组件配置

详细的Options配置可以参考VTable配置文档 www.visactor.io/vtable/opti...

Dataset

用户通过Record将数据传入传入,除了原始数据外,用户还可以通过配置Filter自定义数据的过滤规则,以及通过配置Sort定义数据在表格中的显示顺序;在透视表中,Satistics模块可以对数据进行数据统计,依据用户的配置计算相应的小计、总计、平均等统计信息。

详细的数据统计相关配置可以参考VTable配置文档 www.visactor.io/vtable/opti...

Theme

Theme模块管理表格的全局样式,通过Theme模块可以配置表头单元格和内容单元格的样式(背景、边框、文字样式等),也可以配置表格整体的边框、圆角、阴影等,还可以配置菜单、标题、滚动条等表格组件的样式。

详细的主题相关配置可以参考VTable配置文档 www.visactor.io/vtable/opti...

Layout

Layout模块负责表格的整体布局,包括通过配置生成行列表头,分配单元格的行列号等任务。

在ListTable中,Layout分析columns配置,生成表头单元格信息;在PivotTable中,Layout分析columnTreerowTreecolumnsrows配置,生成行列表头单元格信息;表头单元格的合并信息也在此时产生,以下图为例,由于其中Full Name列配置了多级标题,因此同级的ID列表头为上下两个单元格合并,Full Name列的上层表格为左右两个单元格合并:

在表头单元格信息生成后,表格整体的行列信息(表头区域的行列范围、内容区域的行列范围等),以及表格中每条数据对应的单元格行列坐标也由Layout模块计算得出。

一些布局结构更新操作(树形结构折叠展开,拖拽改变行列位置等),Layout模块会更新表头,表格整体的行列信息和数据对应的单元格行列坐标,随后通过Scenegraph模块更新相应的单元格节点。

State

State模块管理者表格当前的状态,包括冻结、选中、hover、滚动等等的表格状态。在状态改变时,State模块会处理相关的变更信息,改变保存的表格状态,并触发Scenegraph模块的更新,改变相应的单元格节点内容与样式,进而改变画面中表格的展示形态。以列宽改变交互为例:

Event

Event模块负责表格中监听和触发事件,表格内监听的交互事件会触发State模块相应的状态更新,部分表格的状态的更新也会通过Event模块触发表格定义的事件类型。其中Event模块管理事件主要分为三类:

  • 交互事件:Event模块会监听VRender图元的交互事件,并触发相应的表格交互事件(MOUSEMOVE_CELL, CLICK_CELL, MOUSELEAVE_CELL等),供表格内部模块以及用户监听使用。
  • 表格事件:表格事件是指有基础交互触发的表格相应状态改变时,触发的表格定义的事件,例如单元格选择SELECTED_CELL,列宽调整RESIZE_COLUMN,表格滚动SCROLL,拖拽改变表头位置CHANGE_HEADER_POSITION等。
  • 自定义事件:自定义事件是指表格内组件或用户定义的事件,由定义方按需求触发和监听使用,例如显示菜单SHOW_MENU,图例点击切换LEGEND_CHANGE,选择框状态改变CHECKBOX_STATE_CHANGE等。

Scenegraph

Scenegraph模块负责表格场景节点的创建与更新,表格整体场景节点是基于VRender提供的图元创建的场景树结构,按照表格->表头/内容->列->单元格->单元格内容的组织顺序,一层层构建而成。

Scenegraph模块将表格分为以下几个区域:

这几个区域所覆盖的单元格行列区域由Layout模块计算所得,初始化的时候Scenegraph模块会分别创建这个几个区域的的单元格节点。Scenegraph模块除了创建单元格节点外,还提供场景节点相关的查询和更新功能,例如通过行列号查找相应的单元格节点,更新单元格节点内的图元树形,添加和删除单元格节点等。

单元格类型

单元格节点会依据当前单元格类型,在单元格中创建相应的图元:

  • text/link: text/link类型单元格中为Text图元,link类型会有不同的样式及点击跳转交互
  • image/video: image/video类型单元格中为Image图元,video类型有点击播放交互
  • progressbar: progressbar类型单元格为进度图,其中为Rect图元和Text图元的组合
  • sparkline: sparkline类型单元格为迷你图,其中为Line图元和Symbol等图元的组合
  • checkbox: checkbox类型单元格为选中框,其中为Symbol图元和Text等图元的组合
  • chart: chart类型单元格为图表,其中为VChart图表实例

单元格中如果有图标(表头单元格或内容单元格配置icon属性),相应的Image图元也会创建在相应的单元格节点中。

ProgressProxy

ProgressProxyScenegraph模块中的一个子模块,主要负责大数据量下首屏和交互时的性能优化。ProgressProxy模块会定义场景节点中维护的行列最大数量限制,以避免超大数据量下,场景节点过多导致的超长创建和更新时间。在首屏加载过程中,ProgressProxy模块会控制节点的创建,首先创建屏幕范围内的单元格,随后异步渐进完成场景节点的创建。在大数据量滚动时,ProgressProxy模块会动态更新场景节点,滚动期间,按照滚动的方向,一部分单元格会更新其在场景树中的位置,并更新单元格内的图元,完成滚动效果。

Render

VTable的底层渲染由VRender实现,Scenegraph模块组织好的场景树会加载到VRender的Stage中,进行渲染;VRender提供的按需重绘及合并异步渲染能能力,支持了VTable的高性能渲染需求。

VRender参考 github.com/VisActor/VR...

从数据到画面

初始化

接下来,我们来简单介绍一下VTable初始化一个表格的完整流程:

  1. 基础模块初始化

第一步,在创建VTable实例后,会初始化各个模块,创建表格渲染的Canvas元素。Scenegraph模块会创建VRender Stage,用来管理整个渲染过程,并生成基础的场景节点结构;Event模块会绑定表格内使用的交互事件,表格事件和自定义事件;State模块会依据options配置设置表格初始的各项状态。Layout模块依据options计算行列表头信息,以及表格整体的行列信息,从而得到每条数据对应的行列坐标。

  1. 接收处理数据

第二步,数据处理,已经用户配置的过滤和排序规则,处理Record数据。如果有树形结构和数据分析的需求,会进一步处理数据,生成相应的结果信息。完成数据处理后,会更新Layout模块中的表格行列数目信息。

  1. 场景节点生成与渲染

第三步,创建场景节点,依据布局结果和数据,生成相应的单元格场景节点。随后会依据样式配置表格根节点的边框等属性,并生成表格配套组件和其对应的场景节点。最后,依据body部分的单元格尺寸,更新相应容器的尺寸和滚动条节点的状态(尺寸、位置)。

完成所有场景节点的创建更新后,VRender Stage开始渲染整个场景树,表格就在Canvas元素中被绘制出来了。

状态更新

我们再以拖拽改变列宽为例,简单介绍一下VTable状态更新的完整流程:

  1. 接收mousedown事件,如果鼠标位置在列边缘,则开始拖拽改变列宽。State模块改变当前状态,并记录初始鼠标位置;Scenegraph模块显示列宽调整辅助组件,并触发表格重绘。
  1. 接收mousemove事件,如果在拖拽改变列宽过程中,State模块依据初始鼠标位置和当前鼠标位置,计算新列宽;Scenegraph模块更新相应节点的宽度属性和布局,以及列宽调整辅助组件的位置;State模块触发表格事件RESIZE_COLUMNScenegraph模块触发表格重绘。
  1. 接收mouseup事件,如果在拖拽改变列宽过程中,State模块结束列宽调整状态,并触发RESIZE_COLUMN_ENDScenegraph模块隐藏列宽调整辅助组件,并触发表格重绘。

欢迎交流

联系方式

项目官网:www.visactor.io/vtable

微信公众号(通过公众号菜单可以加入微信群和飞书群):

twiter:twitter.com/xuanhun1

今夜无月,期待你点亮星空,感谢Star:

githubgithub.com/VisActor/VT...

更多参考:

  1. 基于 VTable 的多维数据展示的原理与实践 - 掘金
  2. VTable------不只是高性能的多维数据分析表格,开源,免费,百万数据秒级渲染
  3. VisActor------面向叙事的智能可视化解决方案 - 掘金
  4. 火山引擎DataWind产品可视化能力揭秘 - 掘金
  5. 更多 VTable 示例
相关推荐
腾讯TNTWeb前端团队7 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom12 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom12 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom12 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom12 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试