javascript-使用sigma.js展开和折叠
作者:互联网
目标
我正在尝试在sigma.js中实现展开和折叠.在任何节点上单击鼠标右键都将添加新节点并连接其边缘,但它放置在随机位置.
我想在自由空间中添加节点,它们不应碰撞或与其他节点重叠.它应随动画缓慢扩展,并在自由空间区域(如this example. Related)中扩展.
码
<!DOCTYPE html>
<html>
<head>
<title> Airlines Graph Render </title>
<script src="../build/sigma.min.js"></script>
<script src="../src/renderers/canvas/sigma.canvas.edges.curvedArrow.js"></script>
<script src="../plugins/sigma.layout.forceAtlas2/worker.js"></script>
<script src="../plugins/sigma.layout.forceAtlas2/supervisor.js"></script>
<script src="../plugins/sigma.renderers.edgeLabels/settings.js"></script>
<script src="../plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.curve.js"></script>
<script src="../plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.def.js"></script>
<script src="../plugins/sigma.renderers.edgeLabels/sigma.canvas.edges.labels.curvedArrow.js"></script>
<style>
body,html{
width: 100%;
margin: 0px;
padding: 0px;
height: 100%
}
#graph-container {
width:100%;
height: 100%;
}
</style>
</head>
<body>
<div id="graph-container"></div>
<script >
var graph = {
"nodes": [
{
"city": "Dallas",
"area": 999,
"code": 214,
"country": "USA"
},
{
"city": "Austin",
"area": 1180,
"code": 512,
"country": "USA"
},
{
"city": "New York",
"area": 1214,
"code": 646,
"country": "USA"
},
{
"city": "Washington",
"area": 176,
"code": 564,
"country": "USA"
},
{
"city": "Atlanta",
"area": 342,
"code": 518,
"country": "USA"
},
{
"city": "Huston",
"area": 1625,
"code": 281,
"country": "USA"
},
{
"city": "Chicago",
"area": 606,
"code": 312,
"country": "USA"
},
{
"city": "London",
"area": 909,
"code": 312,
"country": "England"
}
],
"edges": [
{
"key": 1,
"source": "Dallas",
"destination": "Austin",
"distance": 200,
"airlines": "British Airways",
"fare": 220
},
{
"key": 2,
"source": "Austin",
"destination": "Dallas",
"distance": 200,
"airlines": "Lufthansa",
"fare": 120
},
{
"key": 3,
"source": "Washington",
"destination": "Dallas",
"distance": 1300,
"airlines": "Lufthansa",
"fare": 300
},
{
"key": 4,
"source": "Atlanta",
"destination": "Washington",
"distance": 600,
"airlines": "Lufthansa",
"fare": 600
},
{
"key": 5,
"source": "Washington",
"destination": "Atlanta",
"distance": 600,
"airlines": "KLM",
"fare": 400
},
{
"key": 6,
"source": "New York",
"destination": "Atlanta",
"distance": 300,
"airlines": "Qatar",
"fare": 1300
},
{
"key": 7,
"source": "Huston",
"destination": "Atlanta",
"distance": 800,
"airlines": "Indigo",
"fare": 400
},
{
"key": 8,
"source": "Atlanta",
"destination": "Huston",
"distance": 800,
"airlines": "Spicejet",
"fare": 600
},
{
"key": 9,
"source": "New York",
"destination": "Chicago",
"distance": 1000,
"airlines": "Air China",
"fare": 500
},
{
"key": 10,
"source": "Chicago",
"destination": "New York",
"distance": 1000,
"airlines": "Jet Airways",
"fare": 200
},
{
"key": 11,
"source": "Dallas",
"destination": "Chicago",
"distance": 900,
"airlines": "Lufthansa",
"fare": 1300
},
{
"key": 12,
"source": "Austin",
"destination": "Huston",
"distance": 160,
"airlines": "Lufthansa",
"fare": 240
},
{
"key": 13,
"source": "Dallas",
"destination": "New York",
"distance": 780,
"airlines": "Lufthansa",
"fare": 300
}
]
};
var g = {
nodes:[],
edges:[]
}
// Generate a random graph:
colors = [
'#617db4',
'#668f3c',
'#c6583e',
'#b956af'
];
sigma.utils.pkg('sigma.canvas.nodes');
sigma.canvas.nodes.border = function(node, context, settings) {
var prefix = settings('prefix') || '';
context.beginPath();
context.arc(
node[prefix + 'x']+15,
node[prefix + 'y'],
node[prefix + 'size']-2,
0,
Math.PI * 2,
true
);
//context.fillStyle = "orange";
context.strokeStyle = node.color || settings('defaultNodeColor');
//get the data from the group
//var data = d3.select(this).data();
context.stroke();
//context.fill();
context.font = "10px Arial";
context.fillStyle = "black";
context.strokeStyle = "black";
//write the text in the context
context.fillText(10,node[prefix + 'x']+15+ 10, node[prefix + 'size']-2-15);
// Adding a border
//context.lineWidth = node.borderWidth || 1;
//context.strokeStyle = node.borderColor || '#fff';
//context.stroke();
context.fillStyle = node.color || settings('defaultNodeColor');
context.beginPath();
context.arc(
node[prefix + 'x'],
node[prefix + 'y'],
node[prefix + 'size'],
0,
Math.PI * 2,
true
);
context.closePath();
context.fill();
};
for (var i = 0; i < graph.nodes.length; i++)
g.nodes.push({
id: graph.nodes[i]['city'],
label: graph.nodes[i]['city'],
x: Math.random(),
y: Math.random(),
size: 8,
color: colors[Math.floor(Math.random() * colors.length)]
});
for (var i = 0; i < graph.edges.length; i++)
g.edges.push({
id: graph.edges[i]['key'],
source: graph.edges[i]['source'],
target: graph.edges[i]['destination'],
size: 8,
label:graph.edges[i]['airlines'],
color: '#668e3e',
type:'curvedArrow'
});
s = new sigma({
graph: g,
renderer: {
container: document.getElementById('graph-container'),
type: 'canvas'
},
settings: {
edgeLabelSize: 'proportional',
minNodeSize: 1,
maxNodeSize: 10,
minEdgeSize: 0.1,
maxEdgeSize: 2,
enableEdgeHovering: true,
edgeHoverSizeRatio: 2,
defaultNodeType: 'border',
defaultNodeColor:"#fff",
mouseEnabled: true,
touchEnabled: true
}
});
//s.settings('autoRescale', false)
s.startForceAtlas2({worker: true, barnesHutOptimize: false});
s.stopForceAtlas2();
s.bind('rightClickNode', function(e) {
console.log(e.type, e.data.node.label, e.data.captor);
var name = 'New City'+Math.random();
s.graph.addNode({
id: name,
label: 'baai',
x: Math.random(),
y: Math.random(),
size: 8,
color: colors[Math.floor(Math.random() * colors.length)]
});
s.graph.addEdge({
id: name +Math.random(),
source: e.data.node.id,
target: name,
size: 8,
label:'bit'+Math.random(),
color: '#668e3e',
type:'curvedArrow'
});
// Edge with Already existing one
s.graph.addEdge({
id: name+Math.random(),
source: 'Huston',
target: name,
size: 8,
label:'New City'+Math.random(),
color: '#668e3e',
type:'curvedArrow'
});
setTimeout(function(){
s.refresh();
},1000)
});
</script>
</body>
</html>
尝试次数
单击节点时,我通过不断增加半径以圆形的方式围绕它放置节点.在JSFiddle中,您可以看到此内容.第一次点击效果不错,但在下次点击时,它又将一个圆圈圈了起来.我应该放置多大的半径,以使其看起来像这样(如屏幕截图所示)?
第二次单击时,它会相对定位并变成此屏幕截图.但是我要实际定位而不是相对定位.
解决方法:
Fruchterman Reingold力导向的图形布局(algorithm summary)将节点之间的力表示为连接钢环的弹簧,并且不断尝试在所有节点之间寻找平衡.
它是available as a plugin in Linkurious(Sigma.js的叉子).此布局可能正是您需要的.
使用您自己的代码,并且仅使用以下依赖项:
sigma.plugins.animate
sigma.layouts.fruchtermanReingold(来自Linkurious分支)
为此,在您启动Force Atlas 2布局的地方,将其替换为以下内容:
sigma.layouts.fruchtermanReingold.configure(sigmaInstance, {easing: 'quadraticOut'});
sigma.layouts.fruchtermanReingold.start(sigmaInstance);
最重要的是,在生成新节点或删除节点之后,您必须重新运行布局:
sigmaInstance.refresh();
sigma.layouts.fruchtermanReingold.start(sigmaInstance);
现在,一些技巧
>真正不需要setTimeout()使其起作用.只要记住在每个图形更新后重新运行力布局即可.
>您的代码似乎可以重现比您的屏幕截图更丰富的可视化效果-带有弯曲的边缘,标签等.确保所有依赖项均已实际加载.
>如果确实使用弯曲的边缘,则力的布局仍然可以正常使用,但是表示可能有点怪异,因此请考虑不使用它.
> Fruchterman-Reingold布局可以使用自定义的持续时间,重力,缓和方法等进行配置.请阅读其文档以获取全部功能.
标签:graph,sigma-js,graph-visualization,javascript 来源: https://codeday.me/bug/20191025/1929784.html