当前的节点渲染和布局把很多部分的功能都揉在一起来实现,维护和添加新功能都比较困难,所以决定把现有的 layout.js、layout.default.js 和 layout.bottom.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'
...
});
切换样式:
minder.useTheme('default');
读取样式:
minder.getStyle('root-radius'); // returns 4
node.getStyle('radius'); // node.getType() 返回 'root', 会自动拼接样式项,返回 4
node.getStyle('padding-left'); // returns 20 发现结尾是 '-left'、'-right' 等的会自动找到样式表描述的数组按照 CSS 的方式查找值
Render 负责渲染工作。
对于一个节点,有两个渲染容器(以前是多个),一个是通过 getContentGroup() 来获取的内容容器,一个是通过 getDecorationGroup() 来获得的装饰容器。布局的时候,内容容器最终决定该节点的渲染大小,装饰容器里的内容会被忽略。
节点的渲染分步进行,按顺序描述是:center, left, right, top, bottom。之前渲染这五个步骤是通过事件的形式来通知,每次渲染都清除了原本的内容重新创建节点,造成性能浪费。修改渲染的机制,改成从模块直接注册渲染的节:
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 负责布局工作,布局一般发生在渲染之后。对一个节点的布局,指的是排列其子树。
允许多种布局,布局注册的方式如下:
KityMinder.registerLayout('default', kity.createClass('DefaultLayout', {
base: Layout,
doLayout: function(node) {
// do layout
}
}));
让节点布局的方式是调用节点的 node.layout([name]) 方法。该方法的执行过程如下:
node.getLayout() 获得节点的布局名称
getLayout()