官网:Cytoscape.js
github:GitHub - cytoscape/cytoscape.js: Graph theory (network) library for visualisation and analysis
注:本文主要讲在vue中如何使用Cytoscape.js,主要参考官方文档,由于文档是英文,翻译过程可能偶有出错,所以本文仅供参考。
cytoscape是一个网络图的可视化工具,大量的生物分子/基因领域的公司用它来做可视化分析。由于它的通用性,慢慢的也被其他领域的人用来做网络的可视化和分析。cytoscape分为两种,一种叫做cytoscape desktop,是一个桌面软件,可以把数据导入然后生成可视化的网络图进行分析;另一种叫做cytoscape.js,是一个javascript库,主要给开发人员使用,来在网页上生成可视化的网络图。我们要用的是后者。
安装
npm i cytoscape --save
引入:
全局引入:在 main.js 中引入
import cytoscape from 'cytoscape';
Vue.prototype.$cytoscape = cytoscape;
局部引入:在需要用到的模块中引入
import cytoscape from 'cytoscape'
简单案例:
一个Cytoscape.js的实例对应一个图表,创建实例的方式如下:
var cy = cytoscape({
container: document.getElementById('MainCy'),
});
一个HTML DOM元素,呈现图形的容器(必须指定宽高,否则渲染不出图表)。
container: document.getElementById('MainCy'),
格式示例
elements: [
{ // node n1
group: 'nodes', // 'nodes'是节点元素, 'edges'是边线元素
//group字段可以自动推断出来,但是指定它会在初始化元素时给您很好的调试消息
data: { //元素数据 (使用json可序列化的数据)
id: 'n1', // 每个元素的必选(string) id,在未定义时自动赋值
parent: 'nparent', // 指示复合节点父id; 未指定则没有父节点
// (`parent` 可以被 `eles.move()` 改变)
},
//临时数据(通常是临时数据或非序列化数据)
scratch: {
_foo: 'bar' // app fields prefixed by underscore; extension fields unprefixed
},
position: { //节点的模型位置(初始化时可选,初始化后必选)
x: 100,
y: 100
},
selected: false, // 元素是否被选中(默认为false)
selectable: true, // 选择状态是否可变(默认为true)
locked: false, // 锁定时,节点的位置是不可变的(默认为false)
grabbable: true, // 节点是否可以被用户抓取和移动
pannable: false, //拖动节点是否会导致平移而不是抓取
classes: ['foo', 'bar'], //元素的类名数组(或空格分隔的字符串)
//除非绝对必要,否则不要使用' style '字段,而是使用STYLESHEET代替
style: { // 会覆盖外部其他样式属性
'background-color': 'red'
}
},
{ // node n2
data: { id: 'n2' },
renderedPosition: { x: 200, y: 200 } //可以选择指定位置在屏幕上渲染像素
},
{ // node nparent
data: { id: 'nparent' }
//复合父节点没有独立的尺寸(位置和大小),因为这些值是由后代节点的位置和尺寸自动推断出来的
},
{ // edge e1
group: 'edges', //可以不指定group,只要指定 'source' 和 'target'就会自动推断为一条边:
data: {
id: 'e1',
source: 'n1', //源节点id(边线来自于该节点)
target: 'n2' //目标节点id(边线到此节点)
// (`source` and `target` 可以被 `eles.move()` 改变)
},
pannable: true // 拖动边缘是否会导致平移
}
],
另一种 elements 配置的语法格式
elements: {
nodes: [
{
data: { id: 'a' },
grabbable: false,
},
{
data: { id: 'b' }
}
],
edges: [
{
data: { id: 'ab', source: 'a', target: 'b' }
}
]
},
配置格式
layout: {
name: 'preset' //布局名称
},
默认布局
如果初始化时没有配置 layout 选项,那么图表默认为 grid 布局
null 布局
将所有节点放在 (0, 0) 处。
layout: {
name: 'null'
},
random 布局
将节点放置在视区内的随机位置
layout: {
name: 'random',
fit: true, // 是否适配图表容器
padding: 100, // 图表布局与图标容器之间的距离
boundingBox: undefined, // 约束布局范围; { x1:50, y1:50, x2:5000, y2:500 } or { x1, y1, w, h }
animate: true, // 渲染时是否以动画方式布局节点位置,默认false
animationDuration: 5000, // 以毫秒为单位的动画持续时间
// animationEasing: undefined, // easing of animation if enabled动画的缓和,如果启用
//一个函数,决定节点是否应该被动画化。所有节点的动画默认为动画启用。当布局开始时,非动画节点被立即定位
// animateFilter: function ( node, i ){ return true; },
ready: ()=>{console.log('ready')}, // 布局ready时的回调函数,默认undefined
stop: ()=>{console.log('stop')}, // 布局stop时的回调函数,默认undefined
// transform: function (node, position ){ return position; } // 变换一个给定的节点位置。对于在离散布局discrete layouts中改变流动方向有用
},
效果
preset 布局
将节点放在 elements 配置中 nodes 的 position 指定的位置,如果没有指定 position,所有点在中心重叠
name: 'preset',
// positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; }
zoom: 1, // 缩放级别 (设置 fit = false 时生效)
pan: {x: 50, y:100}, // 位移距离 (设置 fit = false 时生效)
fit: false,
padding: 30,
// animate: true,
// animationDuration: 500,
// animationEasing: undefined, //
// animateFilter: function ( node, i ){ console.log(node);console.log(i);return true; },
// ready: undefined,
// stop: undefined,
// transform: function (node, position ){ console.log(node);return position; }
grid 布局
将节点放在间隔良好的网格中
name: 'grid',
fit: true,
padding: 30,
boundingBox: undefined, // 约束布局范围; { x1, y1, x2, y2 } or { x1, y1, w, h }
avoidOverlap: true, // 防止节点重叠,如果没有足够的空间,可能会溢出boundingBox
// avoidOverlapPadding: 10, //avoidOverlap: true 时节点周围额外边距
// nodeDimensionsIncludeLabels: false, // 在计算布局算法的节点边界框时排除标签
// spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up
condense: false, // false时使用所有可用空间,true时使用最小空间
rows: 2, // 强制设定网格中的行数,若不设置则自动适配布局
cols: 3, // 强制设定网格中的列数,若不设置则自动适配布局
// position: function( node ){}, // returns { row, col } for element
// sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
//动画相关属性同random布局
**circle **布局
将节点放在一个圆圈中
name: 'circle',
radius: undefined, // 圆的半径
startAngle: 3 / 2 * Math.PI, // 节点从什么弧度开始
sweep: 5, // 第一个和最后一个节点之间应该有多少弧度(默认为整圆)
clockwise: true, // 布局是顺时针(true)还是逆时针/逆时针(false)
sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
concentric 布局
根据指定的指标将节点定位在同心圆中
name: 'concentric',
equidistant: true, // levels之间是否有相等的径向距离,可能导致边框溢出
minNodeSpacing: 30, // 节点外间距最小值(用于半径调整)
height: undefined, //布局区域高度(覆盖container高度)
width: undefined, // 布局区域宽度(覆盖container宽度)
concentric: function( node ){ // 返回每个节点的degree数值(节点连线数量),将degree值较高的节点置于向中心方向的层次中
return node.degree();
},
levelWidth: function( nodes ){ //各level上degree数值的变化(每一个圆上的节点的degree数值变化范围)
console.log(nodes.maxDegree());
// return 1; //设为1,则各level上degree数值相等
// return 2; //设为2,则各level上节点degree数值差范围为2以内,既 差值 < 2
return nodes.maxDegree() / 2; //用算法设置
},
breadthfirst 布局
将节点放在层次结构中,基于图形的宽度首次遍历。它最适合于默认的自上而下模式下的树木和森林,也最适合 circle 模式下的 DAG (有向无环图:Directed Acyclic Graph)。
name: 'breadthfirst',
directed: false, // 树是否向下(或者如果是false,边线可以指向任何方向)
circle: false, //true,将depths放在同心圆上,false,将depths放在上下
grid: false, // 是否创建一个放置DAG的均匀网格(circle: false时生效)
spacingFactor: 1.5, //正间距因子,数值越大,节点之间空间越大(如果引起重叠,注意n/a)
avoidOverlap: true, // 防止节点重叠,如果没有足够的空间,可能会溢出boundingBox
roots: undefined, // the roots of the trees
maximal: false, //是否向下移动节点的自然BFS depths以避免向上的边(DAGS only)
depthSort: undefined, // 一种排序函数,使节点按等深度排序。例如function(a, b){return a.data('weight') - b.data('weight')}
cose 布局
使用物理模拟来布局图形。它适用于非复合图,并且具有额外的逻辑来很好地支持复合图。
name: 'cose',
randomize: false,//随机化节点的初始位置(true)或使用现有位置(false)
componentSpacing: 50,//非复合图中组件之间的额外间距
// nodeRepulsion: function( node ){ return 2048; },//节点排斥(非重叠)乘数Node repulsion (non overlapping) multiplier
// nodeOverlap: 4,//节点排斥(重叠)乘数Node repulsion (overlapping) multiplier
// idealEdgeLength: function( edge ){ return 32; },// 理想的边线(非嵌套)长度
// edgeElasticity: function( edge ){ return 32; },//除数来计算边缘力Divisor to compute edge forces
// nestingFactor: 1.5,//嵌套因子(乘法器)用于计算嵌套边的理想边长Nesting factor (multiplier) to compute ideal edge length for nested edges
gravity: 1,//重力(常数)
numIter: 1000,//要执行的最大迭代次数Maximum number of iterations to perform
initialTemp: 1000,//初始温度(最大节点位移)Initial temperature (maximum node displacement)
coolingFactor: 0.99,//冷却因子(温度如何在连续的迭代之间降低Cooling factor (how the temperature is reduced between consecutive iterations
minTemp: 1.0 //较低的温度阈值(低于此点布局将结束)Lower temperature threshold (below this point the layout will end)
其他扩展布局
其他扩展布局需安装引入对应布局插件才能使用,例如使用 ‘cola’ 布局:
‘cola’ 布局物理模拟(力导向)布局。Cola制作了漂亮的布局结果,它非常流畅地制作动画,并且它有丰富的选项来控制布局。它专注于为相对较小的图形提供美观的结果。
步骤①:安装
npm install cytoscape-cola
步骤②:引入,注册
import cytoscape from 'cytoscape'
import cola from 'cytoscape-cola';
cytoscape.use( cola );
步骤③:配置,使用
layout: {
name: 'cola'
//其他配置...
}
样式格式
初始化时指定的样式可以是函数格式、纯 JSON 格式或字符串格式 — 如果要从服务器中拉下样式,纯 JSON 格式和字符串格式会更有用。
函数格式
style: cytoscape.stylesheet()
.selector('node')
.style({//此处style可以用css替换,如.css({...})
'background-color': 'blue'
}),
JSON格式
style: [
{
selector: 'node',
style: {//此处style可以用css替换,如 css:{...}
'background-color': 'red'
}
}
],
字符串格式
style: 'node { background-color: green; }'
样式属性值通用规则
颜色可以通过名称(例如 red
)、十六进制(例如 #FFFFFF
或 #FFF
)、RGB(例如 rgb(255, 0, 0)
)或 HSL(例如 hsl(0, 100%, 50%)
)。
需要数字的值(如长度)可以用像素值(例如 24px
)、隐式以像素为单位的无单位值(例如 24
)或 em 值(例如 2em
)来指定。大小在 position 中指定,因此屏幕上(渲染)的大小与缩放 1 时指定的大小相同。
不透明度值指定为范围为 0-1 之间的数字(例如 0.5
)。
时间以毫秒或秒为单位测量(例如 250ms
)。
角度以弧度 radians(例如3.14rad
)或度 degrees(例如180deg
)顺时针测量。180deg
指定值列表的属性可以采用以下格式之一进行格式化:
空格分隔的字符串
'red rgb(0,255,0) blue'
请注意,对于颜色列表,这意味着不能在 rgb()
或hsl()
中使用空格。
这是字符串样式表(通常是外部文件)中唯一可能的格式。
一个 JS 数组
['red', 'rgb(0, 255, 0)', 'blue']
此格式可用于函数样式表和 JSON 样式表中。
节点主体常用样式
style: [
{
selector: 'node',
style: {
//形状相关属性
'width': '70',
'height': '50',
'shape': 'triangle', // triangle | rectangle |
//背景色相关属性
'background-color': '#3549fc',
'background-opacity': '0.9',
//边框相关属性
'border-width': '2',
'border-style': 'dashed',
'border-color': 'red',
'border-opacity': '0.8',
//padding相关属性
'padding': '10px',
}
},
],
边线常用样式
{
selector: 'edge',
style: {
'width': '2',
//曲线样式,haystack | straight | straight-triangle | bezier | unbundled-bezier | segments
'curve-style': 'bezier',
'line-color': '#1db1b1',
'line-style': 'solid', //边线样式,solid | dotted | dashed
'line-cap': 'round', //边缘线的帽样式
'line-opacity': '0.8', //边线不透明度,0-1之间
//曲线端点样式,target可替换为source、mid-source、mid-target
'target-arrow-shape': 'triangle-backcurve',// haystack边不支持源箭头和目标箭头
'target-arrow-color': 'red',
'arrow-scale': '1.5',//缩放箭头的大小, number >= 0.
'source-distance-from-node': 10,
'target-distance-from-node': 10,
// 'color': '#2a3b77',
// 'content': 'data(relationship)',
}
},
显示、隐藏元素的样式
style: {
'display': 'none', //不可见,不占空间,节点设置后指向节点的边线也消失,值为'element'则正常显示
'visibility': 'hidden', //不可见,正常占用空间
'opacity': '0', //不可见,正常占用空间
'z-index': '2',//层级
}
标签常用样式
'label': 'data(id)', //标签文本内容
'text-halign': 'center', //垂直对齐方式,left | center | right
'text-valign': 'center', //水平对齐方式,left | center | right
'source-label': 'data(source)', //边线源标签
'source-text-offset': '10', //标签应放置在距源节点的距离
'target-label': 'data(target)',//边线目标标签
'target-text-offset': '20',
//标签文本属性,支持大部分css字体样式
'color': '#f1861b',
'font-size': '20',
'text-transform': 'uppercase', //签文本大小写转换
'text-max-width': '10',
'text-wrap': 'wrap',//基于text-max-width可设置none、wrap、ellipsis
// 'line-height': '60',
还有很多其他属性,可设置标签位置、旋转角度、轮廓、背景、边框等。
影响图形全局UI的常用样式
有些属性影响图形的全局UI,并且仅适用于core。可以使用特殊的 core 选择器字符串来设置这些属性。
{
selector: 'core',
style: {
'active-bg-color': '#78f11b', //用户抓取背景时抓取指示点的背景色
'active-bg-opacity': '0.5', //抓取指示点的透明度
'active-bg-size': '20', //抓取指示点的尺寸
'selection-box-color': '#78f11b', //选择框颜色(按住ctrl或shift同时鼠标拖动可出现选择框)
}
}
其他
//节点重影
'ghost': 'yes',
'ghost-offset-x': '20',
'ghost-opacity': '0.1',
//动画
'transition-property': 'background-color',//要进行动画处理的样式属性,多个可用空格分隔
'transition-duration': '1s',
包含图形级数据的普通对象(即不属于任何特定节点或边线的数据)。用 cy.data()
访问
data: {
keyA:'abc',
keyB:'XXX'
//...
},
注:配置了 zoomingEnabled: false
时生效
zoom: 1, //图形的初始缩放级别。
pan: { x: 0, y: 0 }, //图形的初始平移位置。
minZoom: 1e-50, //图形缩放级别的最小界限。视口的缩放比例不能小于此缩放级别。
maxZoom: 1e50, //图形缩放级别的最小界限。视口的缩放比例不能小于此缩放级别。
zoomingEnabled: true, //是否通过用户事件和编程方式启用缩放图形。
userZoomingEnabled: true, //是否允许用户事件(例如鼠标滚轮、捏合缩放)缩放图形。对缩放的编程更改不受此选项的影响。
panningEnabled: true, //是否用户事件和编程方式启用平移图形。
userPanningEnabled: true, //是否允许用户事件(例如拖动图形背景)平移图形。对平移的编程更改不受此选项的影响。
boxSelectionEnabled: true, //是否启用框选择(即拖动框叠加,然后释放它进行选择)。如果在同时启用平移时启用,则用户必须使用修饰键(shift、alt、控件或命令)才能使用框选择。
selectionType: 'single', //一个字符串,指示用户输入的选择行为。对于'additive',用户做出的新选择将添加到当前选择的元素集中。对于'single',用户进行的新选择将成为当前所选元素的整个集合(即,未选择先前的元素)。
touchTapThreshold: 8, //一个非负整数,指示用户在轻击手势期间分别在触摸设备和台式设备上可以移动的最大允许距离。这使用户更容易点击。这些值具有默认值,因此除非有充分的理由,否则不建议更改这些选项。较大的值几乎肯定会产生不良后果。
desktopTapThreshold: 4, //同上
autolock: false, //默认情况下是否应锁定节点(完全不可拖动)(如果true,则覆盖单个节点状态)。
autoungrabify: false, //默认情况下是否应取消节点的节点化(用户不可抓取)(如果true,则覆盖单个节点状态)。
autounselectify: false, //默认情况下是否应取消选择节点(不可变的选择状态)(如果true,则覆盖单个元素的状态)。
multiClickDebounceTime: 250, //在执行oneclick事件之前,以指定毫秒为单位检查是否是dblclick事件
headless: false, //一个方便的选项,可初始化实例以无外设方式运行。您无需在隐式无外设环境(例如 Node.js)中设置此项。但是,如果要在浏览器中使用无外设实例,则设置它非常方便。
styleEnabled: true, //是否应使用样式, 如果计划渲染图形,则禁用样式没有意义。对于无头(即,在浏览器外部)环境,不需要显示,也不需要样式设置,从而加快了代码的速度。
hideEdgesOnViewport: false, //一种渲染提示,当设置为true时,会使渲染器在操作视口时不渲染edges。这使得平移、缩放、拖动等对大型图形的响应速度更快。由于性能增强,此选项现在基本上没有实际意义。
textureOnViewport: false, //一种渲染提示,设置为true时,true使渲染器在平移和缩放过程中使用纹理而不是绘制元素,从而使大型图形更具响应性。由于性能增强,现在该选项几乎没有意义
motionBlur: false, //渲染提示,设置为true时,使渲染器使用运动模糊效果使帧之间的过渡看起来更平滑。这可以提高大型图的感知性能。由于性能增强,现在该选项几乎没有意义。
motionBlurOpacity: 0.2, //此值控制运动模糊帧的不透明度。较高的值会使运动模糊效果更加明显。由于性能增强,现在该选项几乎没有意义。
wheelSensitivity: 1, //更改变焦时的滚轮灵敏度。这是一个乘法修饰符。因此,介于0和1之间的值会降低灵敏度(缩放较慢),而大于1的值会提高灵敏度(缩放较快)。此选项设置为一个合理的值,该值对于Linux,Mac和Windows上的主流鼠标(Apple,Logitech,Microsoft)非常有效。如果默认值在你的特定系统上看起来太快或太慢,则你的操作系统或专用鼠标可能具有非默认鼠标设置。除非你的应用只能在特定硬件上运行,否则你不应更改此值。否则,冒着使大多数用户缩放得太慢或太快的风险。
pixelRatio: 'auto', //使用手动设置的值(1.0建议,如果设置)覆盖屏幕像素比率。通过减少需要渲染的有效区域,可以将其用于提高高密度显示器的性能,尽管在最新的浏览器版本中,此需求要小得多。如果要使用硬件的实际像素比率,则可以设置pixelRatio: 'auto'(默认)。