简介
本工具可以直观地看到程序遍历图的过程
截图
使用方法
复制以下代码, 保存为html文件
<!DOCTYPE>
<html>
<head>
<title>Cytoscape</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<script src="https://unpkg.com/webcola/WebCola/cola.min.js"></script>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh//cytoscape/cytoscape.js-cola/cytoscape-cola.js"></script>
<meta charset="utf-8">
<style>
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
</style>
<script>
var ifsx = true;
document.onkeydown = function(event) {
var e = event || window.event || arguments.callee.caller.arguments[0];
if (!window.cy) return;
if (e && e.keyCode == 70) {
if (ifsx) {
cy.$("edge").css("curve-style","bezier")
} else {
cy.$("edge").css("curve-style","")
}
ifsx = !ifsx;
event.preventDefault();
} else if(e.keyCode == 40 || e.keyCode == 39 || e.keyCode == 78) {
nxt();
} else if(e.keyCode == 38 || e.keyCode == 37 || e.keyCode == 80) {
pre();
}
};
function read(files) {
if (files.length) {
var file = files[0];
var reader = new FileReader();
reader.onload = function() {
start(this.result);
}
reader.readAsText(file);
}
}
var colorings = [];
var ci = 0;
var timeid = 0;
var history = [];
function update(op) {
color = ['#aaaaaa', 'red', 'yellow', 'blue', 'orange', 'green', 'purple', 'pink'];
if (parseInt(op[2]) > 7) op[2] = 0;
color = color[parseInt(op[2])];
cy.$(`#${op[0]}`).css('background-color', color);
cy.$(`#${op[1]}`).css('background-color', color);
cy.$(`#${op[0]}_${op[1]}`).css('line-color', color);
}
function getcolor(op) {
return [op[0], op[1], cy.$(`#${op[0]}`).css('background-color'), cy.$(`#${op[1]}`).css('background-color'), cy.$(`#${op[0]}_${op[1]}`).css('line-color')]
}
function updatepre(op) {
cy.$(`#${op[0]}`).css('background-color', op[2]);
cy.$(`#${op[1]}`).css('background-color', op[3]);
cy.$(`#${op[0]}_${op[1]}`).css('line-color', op[4]);
}
function pre() {
if (ci <= 0) return;
ci--;
updatepre(history[ci]);
}
function nxt() {
if (ci >= colorings.length) return;
history[ci] = getcolor(colorings[ci]);
update(colorings[ci]);
ci++;
}
function start(data) {
$("#cy").css("display", "block");
$("#file").css("display", "none");
node = {};
edges = [];
nodes = [];
for (var i of data.split('\n')) {
var line = i.split(' ');
if (line[0] == 'c' && line.length > 3) {
colorings.push([line[1], line[2], line[3]]);
} else {
if (line.length < 2) continue;
node[line[0]] = 1, node[line[1]] = 1;
if (line.length > 2)
edges.push({ data: { id: `${line[0]}_${line[1]}`, source: `${line[0]}`, target: `${line[1]}`, weight: `${line[2]}`} });
else
edges.push({ data: { id: `${line[0]}_${line[1]}`, source: `${line[0]}`, target: `${line[1]}`} });
}
}
for (var i in node) {
nodes.push({ data: { id: `${i}` }});
}
createGraph({
nodes: nodes,
edges: edges
})
}
function createGraph(data) {
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
autounselectify: true,
boxSelectionEnabled: false,
layout: {
name: 'cola'
},
style: [
{
selector: 'node',
style: {
'label': 'data(id)',
'background-color':'white',
'border-width': '2px',
'border-color': 'black'
}
}, {
selector: 'edge',
style: {
//'curve-style': 'bezier',
'curve-style': 'none',
'target-arrow-shape': 'triangle',
'line-color': '#aaa',
'target-arrow-shape': 'triangle',
'width': '2px',
'label': 'data(weight)'
}
}
],
elements: data
});
cy.$('node').on('cxttapend', (e)=>{cy.fit(cy.$(`[id='${e.target.id()}']`),200)})
}
</script>
</head>
<body>
<div id="cy" style="display: none;"></div>
<input id="file" type="file" onchange="read(this.files)"/>
</body>
</html>
使用浏览器打开, 选择数据文件即可
数据文件语法:
对于数据文件的每行:
- 如果全部由数字构成, 则表示图的结构:
- 每行两个数字\(u\), \(v\) 表示边的起点和终点, 例如
3 2
或
- 每行三个数字\(u\), \(v\), \(w\) 表示边的起点, 终点和权值, 例如
3 2 1
- 如果该行由字母
c
开始, 则表示一条着色命令,
-
每行由一个字母
c
和三个数字\(u\), \(v\), \(c\)构成, 表示边的起点, 终点和颜色0 : 灰色 1 : 红色 2 : 黄色 3 : 蓝色 4 : 橙色 5 : 绿色 6 : 紫色 7 : 粉色
新的颜色会覆盖旧的颜色, 着色命令将按顺序从上至下以此执行
这是一个符合语法的数据文件内容:
5 8
5 4
5 3
5 2
4 3
3 1
3 2
2 1
c 5 8 1
c 5 4 1
c 5 3 1
c 5 2 1
c 4 3 1
c 3 2 1
c 3 1 1
c 2 1 1
操作
图默认为无向图, 按f
键可转换有向图和无向图
按n
,右箭头 或 下箭头可依次执行着色命令。
按p
,左箭头 或 上箭头可依次撤销着色命令。
右键点击某节点可移动焦点至该节点(不知道有啥用)
平面直角坐标系
适用于平面直角坐标系的可视工具, 文件内容需要为一个符合Js语法的三维数组, 第一维是时间, 第二,三维是x, y坐标
- 0 : 白色
- 1 : 黑色
- 2 : 蓝色
- 3 : 红色
- 4 : 绿色
- 5 : 紫色
<html>
<head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<meta charset="utf-8"/>
<script>
function add(x, y, s, color) {
$("body").append(`<div id="${x}_${y}" style="background: ${color}; height:${s}px; width:${s}px; position: absolute; border: 1px solid; left: ${x}px; top: ${y}px;"></div>`)
}
var width = 30, l = 5;
function update(t) {
$("body").empty();
for (var i = 1; i < t.length; i++) {
for (var j = 1; j < t[i].length; j++) {
var color, x = j + 1, y = i + 1;
if (t[i][j] == 0) color = "white";
else if(t[i][j] == 1) color = "black";
else if(t[i][j] == 2) color = "blue";
else if(t[i][j] == 3) color = "red";
else if(t[i][j] == 4) color = "green";
else if(t[i][j] == 5) color = "purple";
else color = "yellow";
add(l * x + width * (x - 1), l * y + width * (y - 1), width, color);
}
}
}
function read(files) {
if (files.length) {
var file = files[0];
var reader = new FileReader();
reader.onload = function() {
start(eval(this.result));
}
reader.readAsText(file);
}
}
var map, li, timeid;
function start(a) {
map = a;
li = 0;
timeid = setInterval(loop, 1);
}
function loop() {
update(map[li++]);
if (li >= map.length) clearInterval(timeid);
}
</script>
</head>
<body>
<input type="file" onchange="read(this.files)"/>
</body>
</html>