Skip to content

Instantly share code, notes, and snippets.

@biovisualize
Last active December 16, 2015 02:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save biovisualize/5365390 to your computer and use it in GitHub Desktop.
Save biovisualize/5365390 to your computer and use it in GitHub Desktop.
DAG arc diagram
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title></title>
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
var w = 900,
h = 500;
var matrixSize = 8;
function generateDagAdjacencyList(_size){
// Random lower diagonal matrix
var dagMatrix = d3.range(_size).map(function(d, i){
return d3.range(_size).map(function(d2, i2){return (i-i2 > 0) ? +(Math.random() > 0.5): 0;});
});
// adjacencyList = {..., "7":[0,2,5],"8":[0,3,4,7],"9":[2,4,6]}
var adjacencyList = {};
dagMatrix.forEach(function(d, i){
return d.forEach(function(d2, i2){
if(!adjacencyList[i]) adjacencyList[i] = [];
if(!!d2) adjacencyList[i].push(i2);
});
});
// dagObjectList = [{"node":8,"nodeName":"node8","link":[0,3,4,7],"idx":8}, ...]
var dagObjectList = d3.entries(adjacencyList).map(function(d, i){
return {node: parseInt(d.key), nodeName: 'node'+ d.key, link: d.value, idx: i};
});
var sortedList = dagObjectList.sort(function(a, b){return b.link.length - a.link.length;});
return sortedList;
}
var randomDag = generateDagAdjacencyList(matrixSize);
var svg = d3.select('body')
.append('svg')
.attr({width: w, height: h, xmlns: 'http://www.w3.org/2000/svg'});
var rootGroup = svg.append('g')
.classed('root', true)
.attr({transform: 'translate(0,'+h/2+')'});
var markerW = 8;
var marker = svg.append('defs')
.append('marker')
.attr({
id: 'Triangle',
refX: markerW*2,
refY: markerW,
markerUnits: 'strokeWidth',
markerWidth: markerW + markerW,
markerHeight: markerW * 2 + markerW,
orient: 'auto'
})
.append('path')
.attr({d: 'M 0 0 '+markerW*2+' '+markerW+' 0 '+markerW*2+' '+markerW/2+' '+markerW});
var labelW = 60;
var labelH = 20;
var gap = 20;
var linkGenerator = d3.svg.line()
.x(function(d, i){return d[0];})
.y(function(d, i){return d[1];})
.interpolate('cardinal')
.tension(0);
var linkPath = function(d, i, pI){
var neighbourIdx = randomDag.map(function(d, i){return d.node;}).indexOf(d);
var anchor1 = pI*(labelW+gap)+labelW/2;
var anchor2 = neighbourIdx*(labelW+gap)+labelW/2;
var isBackLink = (anchor2-anchor1) < 0;
var deltaAnchors = (anchor2-anchor1)/2;
var path = linkGenerator([[anchor1, (isBackLink) ? 0 : labelH],
[anchor1+deltaAnchors, deltaAnchors*0.8],
[anchor2, (isBackLink) ? 0 : labelH]]);
return path;
};
var links = rootGroup.selectAll('g.links')
.data(randomDag, function(d, i){return d.idx;})
.enter().append('g')
.classed('links', true);
links.selectAll('path.arrow')
.data(function(d, i){return d.link;})
.enter().append('path')
.classed('arrow', true)
.attr({
d: linkPath,
'marker-end': 'url(#Triangle)'
})
.style({fill: 'none', stroke: 'black', opacity: 1, 'stroke-width': 1});
links.selectAll('path.broad')
.data(function(d, i){return d.link;})
.enter().append('path')
.classed('broad', true)
.attr({d: linkPath})
.style({fill: 'none', stroke: 'orangered', opacity: 0.3, 'stroke-width': 20, 'stroke-linecap': 'round'});
var labels = rootGroup.selectAll('g.labels')
.data(randomDag, function(d, i){return d.node;})
.enter().append('g')
.classed('labels', true)
.attr({transform: function(d, i){return 'translate('+(i*(labelW+gap))+',0)';}});
labels.append('rect')
.classed('label-frame', true)
.attr({
x: 0,
y: 0,
width: labelW,
height: labelH,
})
.style({fill: 'skyblue', stroke: 'grey'});
labels.append('text')
.classed('label-text', true)
.attr({
x: 4,
y: 0,
dy: '1em'
})
.style({})
.text(function(d, i){return d.nodeName;});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment