力引导布局是模拟弹簧电荷模型在每两个节点之间添加一个斥力,每条边的两个节点之间添加一个引力,每次迭代节点会在各个斥力和引力的作用下移动位置,多次迭代后节点会静止在一个受力平衡的位置,达到整个模型的能量最小化。力引导布局的结果有良好的对称性和局部聚合性,也比较美观,我们也常常用来模拟人物关系等。
echarts3相比于之前的版本有着不小的变化,其生成力向图的资源在网上较少且不全,这里写一篇博客记录一下。
在引用了echarts.min.js文件后,首先在html中新建一个div作为图表的显示区域:
<div id="chart">div>
并定义样式:
<style media="screen">
#chart{
height: 500px;
width: 100%;
}
style>
之后便开始进行力向图的数据准备,这一步需要对js中的数组和对象有所了解,如果数据格式不对图表是显示不出来的。echarts使用的数据是json格式,最外层用方括号[]表示,而里面的对象用大括号{}表示,对象内的映射用冒号:表示,并列数据用逗号分隔,我一般将其理解为对象数组。
这种形式的使用使得我们能够很方便的从数据库或其他地方调用到图表组件中,这里举一个例子数据如下:
[{category:0,name: 1, value :5,label: '乔布斯'},
{category:1, name: 2,value : 2,label: '丽萨-乔布斯'},
...]
在echarts3的力向图里面主要有两种数据,一种为节点(node)数据,一种为节点与节点之间的关系边(link)数据,这两种数据都是采用的json格式。
首先说明的是node数据:
{category:0,name: 1, value :5,label: '乔布斯'}
每一个{}里面为一个节点,category(该节点类别),name(关系连接的关键字,可以理解为键值中的键,可为string也可为数字)value(节点的值,可以设置节点半径与该值的关系),label(该字段是我用来显示该节点标签的,可以改名),除此之外大家也可以自己设置一些其他字段。
然后是link数据:
{source : 2, target : 1, value : 5, label: '女儿'}
每一个{}里面为一个关系边,source(起点,对应上面的name),target(终点,对应上面的name),value(起点到终点的距离,值越大,权重越大,距离越短),label(显示该关系边标签,用来说明两节点之间的关系)。
在准备好数据之后我们便可以开始设置option,option的设置中如title(标题)、toolbox(工具箱)等都和其他的图标类型差不多,但是有几点需要重点提一下。
这个工具是当我们鼠标移到相应位置时显示的提示,echarts在其他图表中所看到的是这样显示返回参数的:
formatter: '{a} : {b}'
这个是什么意思呢,如果大家可以去看官方文档可以发现有个参数params,我们在浏览器将其log出来:
其中的$vars就是默认要输出的数组,{a}对应seriesName,{b}对应name,但在很多情况下我们需要显示的不仅仅是这些信息,还好echarts可以使用回调函数,我们的所有数据都已经放在data下供我们使用。
正如之前所说已经将标签内容放在为label,而name里面是node的编码(为什么这么做,因为有时面对大量数据获得到的节点关键就是id数字,重新赋值又会显得繁琐麻烦),所以我们在这里使用回调函数:
formatter: function(params){//触发之后返回的参数,这个函数是关键
if (params.data.category !=undefined) {//如果触发节点
return '人物:'+params.data.label;//返回标签
}else {//如果触发边
return '关系:'+params.data.label;
}
}
回调函数是个很有用的东西,我们在echarts的图表配置中会经常遇到。
如果我们对力向图自带的颜色不满意怎么办,有一个轻松的办法即可做到,改变全局的color颜色,如下:
color:['rgb(194,53,49)','rgb(178,144,137)','rgb(97,160,168)']
这里除了可以使用rgb外还可以使用rgba(你问我rgba是什么东西,自己百度),还有可以使用十六进制的颜色。colol数量与节点中的节点类别对应,是依照顺序调用的,也就是说是依照node中的category字段从小到大显示节点的颜色信息。
其实颜色可以与value的值对应,既可以改变节点的颜色也可以改变边的颜色,需要在相应的地方设置,这里就不弄得太麻烦了。
其实这里没啥好说的,和其他图表一样,关键是这里有个问题,如果种类太多,不可能一个个写出来,那么用什么方法呢?
使用回调函数,恭喜你答对了。
在使用回调函数之前,要把数据准备好,一样是json格式:
graph.categories = [{name:'主干人物'},{name:'家人'},{name:'朋友'} ];
这个数据内的长度对应的也是node种类的数量,我们在legend的data中调用这个数据就可以了:
legend: [{
x: 'left',//图例位置
//图例的名称,这里返回短名称,即不包含第一个,当然你也可以包含第一个,这样就可以在图例中选择主干人物
data: graph.categoriesshort.map(function (a) {
return a.name;
})
}]
接下来是sereis的数据
echarts3与之前的变化出来了,label是图形上的文本标签,用于说明图形的一些数据信息,比如值,名称等,label选项在 ECharts 2.x 中放置于itemStyle.normal下,在 ECharts 3 中为了让整个配置项结构更扁平合理,label 被拿出来跟 itemStyle 平级,并且跟 itemStyle 一样拥有 normal, emphasis 两个状态。
正如之前所说,我们将标签的内容都放在label字段下,默认是显示name,不能再直接用类似{a}、{b}形式显示内容,那么我们使用回调函数:
label: {//图形上的文本标签,可用于说明图形的一些数据信息
normal: {
show : true,//显示
position: 'right',//相对于节点标签的位置
//回调函数,你期望节点标签上显示什么
formatter: function(params){
return params.data.label;
},
}
}
关系边的公用线条样式。其中color 支持设置为’source’或者’target’特殊值,设置为’source’时是与起点颜色相同,’target’是与终点颜色相同。
lineStyle: {
normal: {
show : true,
color: 'target',//决定边的颜色是与起点相同还是与终点相同
curveness: 0.3//边的曲度,支持从 0 到 1 的值,值越大曲度越大,也可设置为直线
}
}
除此之外还可以设置宽度、线条类型等
力引导布局相关的配置项,我个人觉得美不美观和这个很相关。
initLayout:进行力引导布局前的初始化布局,初始化布局会影响到力引导的效果。
repulsion:节点之间的斥力因子,这项可以设置为数组形式,不同大小的值会线性映射到不同的斥力,值越大则斥力越大。
gravity:节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
edgeLength:边的两个节点之间的距离,这个距离也会受 repulsion,支持设置成数组表达边长的范围,此时不同大小的值会线性映射到不同的长度,值越小则长度越长。
还有一些其他项的设置会给人带来更好的感受,就不在此一一列举了,结果如图:
option具体代码如下:
var option = {
title: {
text: '人际关系网络图',//标题
subtext: '人物关系:乔布斯',//标题副标题
top: 'top',//相对在y轴上的位置
left: 'center'//相对在x轴上的位置
},
tooltip : {//提示框,鼠标悬浮交互时的信息提示
trigger: 'item',//数据触发类型
formatter: function(params){//触发之后返回的参数,这个函数是关键
if (params.data.category !=undefined) {//如果触发节点
return '人物:'+params.data.label;//返回标签
}else {//如果触发边
return '关系:'+params.data.label;
}
},
},
//工具箱,每个图表最多仅有一个工具箱
toolbox: {
show : true,
feature : {//启用功能
//dataView数据视图,打开数据视图,可设置更多属性,readOnly 默认数据视图为只读(即值为true),可指定readOnly为false打开编辑功能
dataView: {show: true, readOnly: true},
restore : {show: true},//restore,还原,复位原始图表
saveAsImage : {show: true}//saveAsImage,保存图片
}
},
//全局颜色,图例、节点、边的颜色都是从这里取,按照之前划分的种类依序选取
color:['rgb(194,53,49)','rgb(178,144,137)','rgb(97,160,168)'],
//图例,每个图表最多仅有一个图例
legend: [{
x: 'left',//图例位置
//图例的名称,这里返回短名称,即不包含第一个,当然你也可以包含第一个,这样就可以在图例中选择主干人物
data: graph.categoriesshort.map(function (a) {
return a.name;
})
}],
//sereis的数据: 用于设置图表数据之用
series : [
{
name: '人际关系网络图',//系列名称
type: 'graph',//图表类型
layout: 'force',//echarts3的变化,force是力向图,circular是和弦图
draggable: true,//指示节点是否可以拖动
data: graph.nodes,//节点数据
links: graph.links,//边、联系数据
categories: graph.categories,//节点种类
focusNodeAdjacency:true,//当鼠标移动到节点上,突出显示节点以及节点的边和邻接节点
roam: true,//是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
label: {//图形上的文本标签,可用于说明图形的一些数据信息
normal: {
show : true,//显示
position: 'right',//相对于节点标签的位置
//回调函数,你期望节点标签上显示什么
formatter: function(params){
return params.data.label;
},
}
},
//节点的style
itemStyle:{
normal:{
opacity:0.9,//设置透明度为0.8,为0时不绘制
},
},
// 关系边的公用线条样式
lineStyle: {
normal: {
show : true,
color: 'target',//决定边的颜色是与起点相同还是与终点相同
curveness: 0.3//边的曲度,支持从 0 到 1 的值,值越大曲度越大。
}
},
force: {
edgeLength: [100,200],//线的长度,这个距离也会受 repulsion,支持设置成数组表达边长的范围
repulsion: 100//节点之间的斥力因子。值越大则斥力越大
}
}
]
};