!!!###!!!title=2.2 VTable元素与场景树的表达关系——VisActor/VTable 社区贡献者文档!!!###!!!!!!###!!!description=---title: 2.2 VTable元素与场景树的表达关系 key words: VisActor,VChart,VTable,VStrory,VMind,VGrammar,VRender,Visualization,Chart,Data,Table,Graph,Gis,LLM--- 在VTable中一个元素从代码到展现在我们面前的生动的表格的流程是什么呢?我的理解是,VTable会先创建一个Table实例,接着通过渲染Canvas元素的方式初始化各个表格元素模块,**初始化元素模块的时候会由SceneGraoh创建舞台Stage,并生成不同类型的基础场景树节点结构容器。**后续便是由DataSet模块处理表格内部数据根据不同的数据展示需求来处理生成不同的数据结构,另外结合Layout模块、Event模块等其余模块的辅助,赋以表格布局整齐,可交互的特性。做完所有的准备后调用底层VRender的渲染能力,依照着前面我们提到的搭建的Stage的蓝图,将抽象的场景树结构渲染成为丰富多彩的表格了。 <img src='https://cdn.jsdelivr.net/gh/xuanhun/articles/visactor/sourcecode/img/DHefbI3iZo1kW7xb4COc1Mnjn7b.gif' alt='' width='1000' height='auto'> 本文要解释的就是场景树初始化表格容器的过程; !!!###!!!

在VTable中一个元素从代码到展现在我们面前的生动的表格的流程是什么呢?我的理解是,VTable会先创建一个Table实例,接着通过渲染Canvas元素的方式初始化各个表格元素模块,**初始化元素模块的时候会由SceneGraoh创建舞台Stage,并生成不同类型的基础场景树节点结构容器。**后续便是由DataSet模块处理表格内部数据根据不同的数据展示需求来处理生成不同的数据结构,另外结合Layout模块、Event模块等其余模块的辅助,赋以表格布局整齐,可交互的特性。做完所有的准备后调用底层VRender的渲染能力,依照着前面我们提到的搭建的Stage的蓝图,将抽象的场景树结构渲染成为丰富多彩的表格了。

本文要解释的就是场景树初始化表格容器的过程;

相关源码位置

  • package/vtable/src/scenegrapg/groupcreater/init-scenegraph.ts 场景树容器的初始化

  • package/vtable/src/core/BaseTable.ts 场景树核心类的定义文件

  • package/vtable/src/scenegraph/grapghic/group.ts 为表格渲染扩展的分组管理Group类,用于控制表格的布局、尺寸和渲染,最后返回的实例是一个表格中的分组对象,可以是单元格组、表头组、冻结列组等。

初始化流程

根节点的初始化

 scene.tableGroup = new Group({
      x: 0, 
      y: 0,
      width,
      height,
      clip: true, pickable: false 
  });
  scene.tableGroup.role = 'table';    

这里贴上VRender文档关于Group类这两个clip,pickable的说明,创建Group时会配置坐标,尺寸以及这俩个属性;

pickable: 图元是否可以交互,false的话不会响应任何事件(只显示不能交互)

clip: group设置clip后,会依据width height裁剪超出范围外的子元素部分(类似于overflow: hidden)

场景树其余节点的初始化

function initSceneGraph(scene: Scenegraph) {
  const width = scene.table.tableNoFrameWidth;
  const height = scene.table.tableNoFrameHeight;

  // 根容器
  scene.tableGroup = new Group({ x: 0, y: 0, width, height, clip: true });

  // 创建各子容器的Group实例
  const colHeaderGroup = createContainerGroup(
    0,
    0,
    !(scene.table.options as ListTableConstructorOptions).enableTreeStickCell
  );
  
  //设置colHeader的role属性为'col-header'
  colHeaderGroup.role = 'col-header';
  scene.colHeaderGroup = colHeaderGroup;
}



    

这里以ColHeaderGroup的创建源码为示例


function createContainerGroup(width: number, height: number, clip?: boolean) {
  return new Group({
    x: 0,
    y: 0,
    width,
    height,
    clip: clip ?? false,
    pickable: false
  });
}
    

createContainerGroup返回Group实例的过程

添加到根节点

scene.tableGroup.addChild(bodyGroup);
scene.tableGroup.addChild(rowHeaderGroup);
scene.tableGroup.addChild(bottomFrozenGroup);
//...
//其余节点类似    

将生成的不同节点依次添加到根节点,在源码注释中表明添加顺序不同会有一定影响;

总结

在scenegraph类中,初始化场景树时把当前 Scenegraph 实例传入initSceneGraph函数(源自/init-scenegraph.ts ),深入initSceneGraph不难看出,不同类型的表格子单元在创建场景树的同时通过createContainerGroup返回一个Group实例,然后设置了实例上的 role 属性来标识其功能,最后分别加入到根容器TableGroup中;

至此,容器的初始化部分完成,生成了场景树中的不同类型元素的容器节点(Group);

本文档由以下人员修正整理

玄魂