提交 8540e47d authored 作者: Christof Angermueller's avatar Christof Angermueller

Add dotviz.html

上级 f8740749
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/dagre-d3/v0.1.5/dagre-d3.min.js"></script>
<script type='text/javascript' src="http://cpettitt.github.io/project/graphlib-dot/v0.4.10/graphlib-dot.min.js"></script>
</head>
<body>
<style>
.svg {
margin-left:auto;
margin-right:auto;
display:block;
position: fixed;
border: 2px solid black;
top:1%; left:1%; right:1% bottom=1%
}
.nodeRect {
stroke: black;
border: 3px solid black;
}
.nodeEllipse {
stroke: black;
border: 3px solid black;
}
.nodeText {
color: black;
}
.edge {
stroke: black;
stroke-width: 3px;
cursor: pointer;
}
.edgeLabelRect {
stroke: black;
border: 1px solid black;
fill: skyblue;
opacity: 0.9;
}
.edgeLabelText {
fill: black;
text-anchor: start;
}
.arrowHead {
stroke: black;
stroke-width: 3px;
fill: black;
}
</style>
<input type="file" id="files" name="fileSelector"/>
<script type="text/javascript">
function dotViz(path) {
console.log(path);
// Global attributes
var pad = 10;
d3.select('body').select('svg').remove();
var svg = d3.select('body').append('svg')
.attr('class', 'svg')
.attr('width', '90%')
.attr('height', '90%');
var pane = svg.append('g');
// Definition head of edges
svg.append("defs").append("marker")
.attr("id", 'edgeArrow')
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("refX", 3)
.attr("refY", 3)
.attr("orient", "auto")
.append("path")
.attr("d", "M0,0 L6,3 L0,6 Z")
.attr('style', 'arrowHead');
function textSize(text, attr) {
var t = svg.append('text').text(text);
if (typeof(attr) != 'undefined') {
for (a in attr) {
t.attr(a, attr[a]);
}
}
var bbox = t.node().getBBox();
t.remove();
return bbox;
}
var dotGraph;
var graph = {};
var nodes = [];
var edges = [];
d3.text(path, function(data) {
dotGraph = graphlibDot.parse(data);
// Calculate width and height
var posMax = [0, 0];
for (var nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.value.pos = node.value.pos.split(',').map(function(d) {return parseInt(d);});
node.value.width = parseInt(node.value.width);
node.value.height = parseInt(node.value.height);
posMax[0] = Math.max(posMax[0], node.value.pos[0] + node.value.width);
posMax[1] = Math.max(posMax[1], node.value.pos[1] + node.value.height);
}
dotWidth = posMax[0];
dotHeight = posMax[1];
svg.attr('viewBox', '0,0,' + dotWidth + ',' + dotHeight);
var scaleDotX = d3.scale.linear().domain([0, dotWidth + 100]).range([0, dotWidth]);
var scaleDotY = d3.scale.linear().domain([-25, dotHeight + 100]).range([0, dotHeight]);
// Parse nodes
var i = 0;
for (nodeId in dotGraph._nodes) {
var node = dotGraph._nodes[nodeId];
node.index = i++;
// x, y is center of node (not corner)
node.x = scaleDotX(node.value.pos[0]);
node.y = scaleDotY(dotHeight - (node.value.pos[1] + node.value.height));
var size = textSize(node.value.label, {'class': 'nodeText'});
node.value.width = size.width + 2 * pad;
node.value.height = size.height + 2 * pad;
node.value.cx = node.value.width / 2;
node.value.cy = node.value.height / 2;
node.fixed = true;
nodes.push(node);
dotGraph._nodes[nodeId] = node;
}
// Parse edges
for (edgeId in dotGraph._edges) {
var edge = dotGraph._edges[edgeId];
edge.source = dotGraph._nodes[edge.u].index;
edge.target = dotGraph._nodes[edge.v].index;
var size = textSize(edge.value.label, {'class': 'edgeLabelText'});
edge.value.width = size.width + 2 * pad;
edge.value.height = size.height + 2 * pad;
edges.push(edge);
dotGraph._edges[edgeId] = edge;
}
// Setup graph
graph['nodes'] = nodes;
graph['edges'] = edges;
var isEdgeOver = false;
var isEdgeLabelOver = false;
// Add edges
edges = pane.append('g').attr('id', 'edges').selectAll('path').data(graph['edges']).enter().append('path')
.attr('class', 'edge')
.attr('marker-mid', 'url(#edgeArrow)')
.on('mouseover', function(d) {
var edgeLabel = pane.select('#edgeLabels .' + d.id);
edgeLabel.attr('style', 'display: inline');
})
.on('mouseout', function(d) {
if (!isEdgeLabelOver) {
var edgeLabel = pane.select('#edgeLabels .' + d.id);
edgeLabel.attr('style', 'display: none');
}
});
// Add edge labels
edgeLabels = pane.append('g').attr('id', 'edgeLabels').selectAll('g').data(graph['edges']).enter().append('g')
.attr('style', 'display: none')
.attr('class', function(d) {return d.id;})
.on('mouseover', function(d) {
isEdgeLabelOver = true;
var edgeLabel = d3.select(this);
edgeLabel.attr('style', 'display: inline');
})
.on('mouseout', function(d) {
var edgeLabel = d3.select(this);
edgeLabel.attr('style', 'display: none');
isEdgeLabelOver = false;
});
var edgeLabelsRect = edgeLabels.append('rect')
.attr('class', 'edgeLabelRect')
.attr('fill', 'white')
.attr('width', function(d) {return d.value.width;})
.attr('height', function(d) {return d.value.height;})
.attr('rx', 5)
.attr('ry', 5);
var edgeLabelsText = edgeLabels.append('text')
.attr('class', 'edgeLabelText')
.attr('x', function(d) {return pad;})
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;});
// Add nodes
nodes = pane.append('g').attr('id', 'nodes').selectAll('g').data(graph['nodes']).enter().append('g');
function fillColor(f) {
return typeof(f) == 'undefined' ? 'white' : f;
}
nodes.each(function(d) {
sel = d3.select(this);
var shape;
if (d.value.shape == 'ellipse') {
shape = sel.append('ellipse')
.attr('class', 'nodeEllipse')
.attr('cx', d.value.cx)
.attr('cy', d.value.cy)
.attr('rx', d.value.width * 0.6)
.attr('ry', d.value.height * 0.6);
} else {
shape = sel.append('rect')
.attr('class', 'nodeRect')
.attr('width', d.value.width)
.attr('height', d.value.height);
}
shape.attr('fill', fillColor(d.value.fillcolor));
});
var nodesText = nodes.append('text')
.attr('class', 'nodeText')
.attr('x', pad)
.attr('dy', function(d) {return d.value.height - pad - 5;})
.text(function(d) {return d.value.label;});
// Update graph
function updateGraph() {
// Update nodes
nodes.attr('transform', function(d) { return 'translate(' + (d.x - d.value.cx) + ' ' + (d.y - d.value.cy) + ')'; });
// Update edges
edges.attr('d', function(d) {
return 'M' + d.source.x + ',' + d.source.y + ' L' + 0.5 * (d.source.x + d.target.x) + ',' + 0.5 * (d.source.y + d.target.y) + ' L' + d.target.x + ',' + d.target.y;
});
// Update edge labels
edgeLabels.attr('transform', function(d) {
return 'translate(' + (0.5 * (d.source.x + d.target.x - d.value.width)) + ',' + (0.5 * (d.source.y + d.target.y - d.value.height)) + ')';
});
}
// Drag-start event handler
function dragStart(d) {
d3.event.sourceEvent.stopPropagation();
d.fixed = true;
}
// Zoom and translate event handler
function zoom(d) {
pane.attr('transform', 'translate(' + d3.event.translate + ') scale(' + d3.event.scale + ')');
}
// Force layout
var layout = d3.layout.force()
.nodes(graph['nodes'])
.links(graph['edges'])
.size([dotWidth, dotHeight])
.gravity(0.2)
.charge(-6000)
.linkDistance(75)
.linkStrength(0.1)
.on('tick', updateGraph);
// Drag behavour
var drag = layout.drag()
.on('dragstart', dragStart);
nodes.call(drag);
// Zoom behaviour
var bZoom = d3.behavior.zoom()
.scaleExtent([0.2, 8])
.on('zoom', zoom);
svg.call(bZoom);
// Start force layout
//updateGraph();
layout.start();
});
}
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
dotViz(files[0].name);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
</body>
</html>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论