UNPKG

kityminder

Version:
138 lines (99 loc) 4.74 kB
KityMinder 渲染和布局重构方案 ===== ## 背景 当前的节点渲染和布局把很多部分的功能都揉在一起来实现,维护和添加新功能都比较困难,所以决定把现有的 layout.js、layout.default.js 和 layout.bottom.js 重构。 ## 约定 为了不产生误会,下面约定一些词汇的意思。 样式:对节点或脑图其他内容的外观的描述。 渲染:对节点的绘制的过程。渲染参照的坐标系是节点画布的坐标系。 布局:对节点定位的过程,发生在渲染之后。定位使用的坐标系是脑图画布的坐标系。 节点树多边形:表示一个节点以及其子树所占的多边形区域。 ## 样式、渲染和布局的梳理 ### Theme 负责注册和管理样式。 注册样式: ```js KityMinder.registerTheme( 'default', { 'root-padding': [30, 20], 'root-color': 'black', 'root-background': '#A4c5c0', 'root-stroke': 'none', 'root-radius': 4, 'root-space': [10, 5], 'root-font-family': 'Arial', 'root-font-size': 14, 'main-connect-width': 2, 'main-connect-color': 'white', 'main-connect-type': 'arc', 'sub-connect-type': 'fold' ... }); ``` 切换样式: ```js minder.useTheme('default'); ``` 读取样式: ```js minder.getStyle('root-radius'); // returns 4 ``` ```js node.getStyle('radius'); // node.getType() 返回 'root', 会自动拼接样式项,返回 4 node.getStyle('padding-left'); // returns 20 发现结尾是 '-left'、'-right' 等的会自动找到样式表描述的数组按照 CSS 的方式查找值 ``` ### Render Render 负责渲染工作。 对于一个节点,有两个渲染容器(以前是多个),一个是通过 `getContentGroup()` 来获取的内容容器,一个是通过 `getDecorationGroup()` 来获得的装饰容器。布局的时候,内容容器最终决定该节点的渲染大小,装饰容器里的内容会被忽略。 节点的渲染分步进行,按顺序描述是:`center`, `left`, `right`, `top`, `bottom`。之前渲染这五个步骤是通过事件的形式来通知,每次渲染都清除了原本的内容重新创建节点,造成性能浪费。修改渲染的机制,改成从模块直接注册渲染的节: ```js KityMinder.registerModule( 'MyModule', { commands: { ... }, events: { ... }, renderers: { left: kity.createClass( 'MyRenderer', { base: Renderer, create: function(node) { this.content = new kity.Group(); // 添加元素 node.getContentGroup().addShape(this.content); }, update: function(node) { var content = this.content; // update content // 需要返回更新后内容所占的矩形区域,简单的返回形式是 return this.content.getRenderBox(); return { x: 30, y: -30, width: 24, height: 24 }; } } } }); ``` 用 `renderers` 节来描述渲染器,节的 `key` 指定渲染器使用的阶段,节的 `value` 给出渲染器的类。渲染器需要继承 `Renderer` 类,并且实现两个抽象方法:`create()` 和 `update()`。 `create` 方法只会在节点创建的时候调用一次,此时应该创建渲染所需要的元素,并且附加到节点上。 `update` 方法会在节点需要重新渲染的时候被调用,此时可以选择隐藏、显示或更新元素。 在渲染过程中,节点提供下述信息: - `node.getStyle(name)` 获得节点当前的某个样式描述 - `node.getContentBox()` 获得节点当前已渲染的内容在节点的 ConentGroup 的坐标系中所占的矩形区域。 - `node.getType()` 获得节点的类型('root' | 'main' | 'sub') 要触发一个节点的渲染,直接调用 'node.render()' 即可。 ### Layout Layout 负责布局工作,布局一般发生在渲染之后。对一个节点的布局,指的是排列其子树。 允许多种布局,布局注册的方式如下: ```js KityMinder.registerLayout('default', kity.createClass('DefaultLayout', { base: Layout, doLayout: function(node) { // do layout } })); ``` 让节点布局的方式是调用节点的 `node.layout([name])` 方法。该方法的执行过程如下: - 调用 `node.getLayout()` 获得节点的布局名称 - 如果节点中的 data 包含布局名称,返回该布局名称,否则下一步 - 如果节点是根节点,返回 KityMinder.getDefaultLayout() - 返回父节点的 `getLayout()` - 根据布局名称获得相应的布局方法,把节点作为参数传进去调用