layout 布局
简介节点和链接绘制关系图布局算法的作用G2 实现的布局算法使用方式如何实现自己的布局算法示例简介G2可以通过点和边来实现树图、网络图等关系图,而节点的位置需要使用布局算法来确定,常见的布局算法分为:
树的布局算法,有正交布局、径向布局、缩进布局、圆锥布局等图的布局算法,有力导布局、MDS 布局等 上面的布局算法在 D3 中都有介绍,本章仅介绍 G2 实现的布局算法和一些约定。 节点和链接关系图一般使用节点-链接法绘制,使用节点表示对象,用线(或者边)表示关系。节点链接法的布局有几个原则:
节点不能相互遮挡、边尽量避免交叉节点的不能移出边界,尽量提升空间利用率 绘制关系图使用节点-链接法绘制关系图需要两份数据,节点的数据和边的数据。由于G2中一个View只能使用一个数据源,所以在 G2 中绘制关系图需要两个 View,所以在 G2 中绘制关系图的步骤如下:
声明节点和边的数据创建图表绘制边,保证节点绘制在边上面XXX绘制节点
id="c1" class="chart-container">
var nodes = [// 节点信息:类别、ID,位置 x,y{id: '0',name: '开始',type: 'start',x: 50,y: 10},{id: '1',name: '步骤一',type: 'action',x: 50,y: 20},{id: '2',name: '步骤二',type: 'action',x: 50,y: 30},{id: '3',name: '条件',type: 'condition',x: 50,y: 40},{id: '4.1',name: '分步骤一',type: 'action',x: 40,y: 50},{id: '4.2',name: '分步骤二',type: 'action',x: 60,y: 50},{id: '5',name: '汇总',type: 'action',x: 50,y: 60},{id: '6',name: '结束',type: 'end',x: 50,y: 70}];var edges = [{source: '0', target: '1'},{source: '1', target: '2'},{source: '2', target: '3'},{source: '3', target: '4.1'},{source: '3', target: '4.2'},{source: '4.1', target: '5'},{source: '4.2', target: '5'},{source: '5', target: '6'}];var Stat = G2.Stat;var chart = new G2.Chart({id: 'c1',width: 800,height: 500,plotCfg: {margin: [0,0]}});var defs = {x: {min: 0,max:100},y: {min: 0, max:100},'..x': {min: 0,max:100},'..y': {min: 0,max:100}};// 首先绘制 edges,点要在边的上面// 创建单独的视图var edgeView = chart.createView();edgeView.source(edges, defs);edgeView.coord().reflect(); // 从上到下edgeView.axis(false);edgeView.tooltip(false);// Stat.link 方法会生成 ..x, ..y的字段类型,数值范围是 0-1edgeView.edge().position(Stat.link('source*target',nodes)).color('#ccc');// 绘制节点var nodeView = chart.createView();nodeView.coord().reflect(); // 从上到下nodeView.axis(false);nodeView.source(nodes, defs);nodeView.point().position('x*y').color('steelblue').label('name', {offset: 10}).tooltip('name');chart.render();
注意事项:
由于节点和链接在两个视图上,所以需要统一两个视图的x,y的度量链接需要使用节点计算线(边)的起始、结束为止,所以需要统计函数 Stat.link节点中需要 x, y, id 字段,方便边的起始、结束点计算 布局算法的作用在 G2 中只要我们知道节点的位置和对应的边就能绘制出关系图,在 G2 中布局算法不是必须的,只要能够计算出节点的位置即可,计算出来的节点需要满足:
节点中需要 x, y, id 字段,方便边的起始、结束点计算计算出来的 x, y 的值都要分布在 [0 - 1] 的范围内
G2 实现的布局算法G2 目前仅支持了树的正交布局,保证树的空间利用率最高
正交布局的API
使用方式使用正交布局的步骤
指定数据源使用布局算法计算树节点的位置,获取树节点之间的边分别创建边的视图和节点的视图,传入数据源渲染
id="c2" class="chart-container">
// 指定数据源var data = [{name: 'root',children: [{name: 'a',children: [{name: 'a1'}, {name: 'a2'}]}, {name: 'b',children: [{name: 'b1',children: [{name: 'b11'}]}]}, {name: 'c'}]}];var layout = new G2.Layout.Tree({nodes: data});var nodes = layout.getNodes();var edges = layout.getEdges();var Stat = G2.Stat;var chart = new G2.Chart({id: 'c2',width: 800,height: 500,plotCfg: {margin: [20,0]}});var defs = {x: {min: 0,max:1},y: {min: 0, max:1}/*, 由于 ..x和..y的默认大小就是 0-1,所以可以不设置'..x': {min: 0,max:1},'..y': {min: 0,max:1}*/};// 首先绘制 edges,点要在边的上面// 创建单独的视图var edgeView = chart.createView();edgeView.source(edges, defs);edgeView.coord().reflect(); // 从上到下edgeView.axis(false);edgeView.tooltip(false);// Stat.link 方法会生成 ..x, ..y的字段类型,数值范围是 0-1edgeView.edge().position(Stat.link('source*target',nodes)).color('#ccc');// 绘制节点var nodeView = chart.createView();nodeView.coord().reflect(); // 从上到下nodeView.axis(false);nodeView.source(nodes, defs);nodeView.point().position('x*y').color('steelblue').label('name', {offset: 10}).tooltip('name');chart.render();
如何实现自己的布局算法实现自己的布局算法非常容易只要满足以下条件:
节点的返回值中存在 x, y 字段节点和边能够通过id 相互关联起来 使用自己布局算法的注意事项:
统一边和节点视图的 x,y 度量的大小范围 示例我们以最简单的随机布局来介绍如何实现自己的算法,步骤如下:
设定数据源随机指定节点的位置在G2中使用布局算法
id="c3" class="chart-container">
var data = [{id: '1', name: '1'},{id: '2', name: '2'},{id: '3', name: '3'},{id: '4', name: '4'},{id: '5', name: '5'},{id: '6', name: '6'}];var edges = [{source: '0', target: '1'},{source: '1', target: '2'},{source: '2', target: '3'},{source: '3', target: '5'},{source: '3', target: '6'},{source: '4', target: '2'},{source: '5', target: '6'}];// 自己的随机布局算法function layout(nodes) {var rst = [];nodes.forEach(function(node) {var obj = {};obj.id = node.id;obj.name = node.name;obj.x = Math.random();obj.y = Math.random(); // 使得 x,y随机的分布在0-1范围内rst.push(obj);});return rst;}// 调用布局算法var nodes = layout(data);var Stat = G2.Stat;var chart = new G2.Chart({id: 'c3',width: 800,height: 500,plotCfg: {margin: [20,20]}});var defs = {x: {min: 0,max:1},y: {min: 0, max:1}/*, 由于 ..x和..y的默认大小就是 0-1,所以可以不设置'..x': {min: 0,max:1},'..y': {min: 0,max:1}*/};// 首先绘制 edges,点要在边的上面// 创建单独的视图var edgeView = chart.createView();edgeView.source(edges, defs);edgeView.coord().reflect(); // 从上到下edgeView.axis(false);edgeView.tooltip(false);// Stat.link 方法会生成 ..x, ..y的字段类型,数值范围是 0-1edgeView.edge().position(Stat.link('source*target',nodes)).color('#ccc');// 绘制节点var nodeView = chart.createView();nodeView.coord().reflect(); // 从上到下nodeView.axis(false);nodeView.source(nodes, defs);nodeView.point().position('x*y').size(10).label('name', {offset: 0}).tooltip('name');chart.render();
另外,在使用过程中可以从其他框架迁移相应的布局算法。
当前内容版权归 蚂蚁金服 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 蚂蚁金服 .上一篇:下一篇:<div class="
