UNPKG

dc.graph

Version:

Graph visualizations integrated with crossfilter and dc.js

185 lines (162 loc) 6.13 kB
<!DOCTYPE html> <html> <head> <title>Titan viewer</title> <meta charset="UTF-8"> <link rel="icon" href="img/favicon.png" type="image/x-icon" /> <link rel="stylesheet" type="text/css" href="css/dc.graph.css"/> <link rel="stylesheet" type="text/css" href="css/dc.css"/> <script type="text/javascript" src="js/d3.js"></script> <script type="text/javascript" src="js/crossfilter.js"></script> <script type="text/javascript" src="js/dc.js"></script> <script type="text/javascript" src="js/queue.js"></script> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/lodash.js"></script> <script type="text/javascript" src="js/cola.js"></script> <script type="text/javascript" src="js/dc.graph.js"></script> <script type="text/javascript" src="js/runner.js"></script> </head> <body> <div id="graph" class="chart"></div> <script type="text/javascript"> var querystring = (function(a) { if (a == "") return {}; var b = {}; for (var i = 0; i < a.length; ++i) { var p=a[i].split('=', 2); if (p.length == 1) b[p[0]] = ""; else b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " ")); } return b; })(window.location.search.substr(1).split('&')); var diagram = dc_graph.diagram('#graph'); var url = querystring.url, vertices_url = url + '/vertices', edges_url = url + '/edges'; var interval = url.interval || 1000; function nocache_query() { return '?nocache=' + Date.now(); } var runner = make_runner(init, step, interval); runner.start(); function init() { // basic diagram setup diagram .width($(window).width()) .height($(window).height()) .showLayoutSteps(true) .sourceAccessor(function(e) { return e.value._inV; }) .targetAccessor(function(e) { return e.value._outV; }); // aesthetics: look at kv.value for node/edge attributes and return appropriate values diagram .nodeStrokeWidthAccessor(0) // turn off outlines .nodeRadiusAccessor(function(kv) { switch(kv.value.node_type) { case 'Router': return 15; case 'Subnet': return 20; case 'VirtualMachine': return 10; default: return 10; } }) .nodeFitLabelAccessor(false) .nodeFillAccessor(function(kv) { // some arbitrarily-chosen colors from colorbrewer2.org switch(kv.value.node_type) { case 'Router': return '#377eb8'; case 'VirtualMachine': return '#4daf4a'; case 'Subnet': return '#e41a1c'; default: return 'grey'; } }) .nodeLabelAccessor(function(kv) { switch(kv.value.node_type) { case 'Router': return kv.value.router_name; case 'VirtualMachine': return kv.value.display_name; case 'Subnet': return kv.value.subnet_name; } }) .edgeStrokeWidthAccessor(function(kv) { return kv.value._label === 'path' ? 2 : 1 }) .edgeLabelAccessor(function(kv) { if(kv.value._label === 'connects_to') return kv.value.ip_address; else return null; }) .edgeArrowheadAccessor(function(kv) { return kv.value._label === 'path' ? 'vee' : null; }) .on('end', function() { runner.endStep(); }); // legend diagram.legend( dc_graph.legend().x(700).y(20).exemplars({ 'Virtual Machine': { node_type: 'VirtualMachine' }, Subnet: { node_type: 'Subnet' }, Router: { node_type: 'Router' } })); // respond to browser resize (not necessary if width/height is static) $(window).resize(function() { diagram .width($(window).width()) .height($(window).height()) }); load(function() { diagram.render(); }); } function step() { load(function() { diagram.redraw(); }); } function load(k) { queue() .defer(d3.json, vertices_url + nocache_query()) .defer(d3.json, edges_url + nocache_query()) .await(function(error, vertices, edges) { if(error) throw new Error(error); var edge_ndx = crossfilter(edges.results), node_ndx = crossfilter(vertices.results); // when there will be exactly one or zero items in a group, a reasonable reduction // is just to use the row or null function one_zero_reduce(group) { group.reduce( function(p, v) { return v; }, function() { return null; }, function() { return null; } ); } var nodeDimension = node_ndx.dimension(function(d) { return d._id; }), edgeDimension = edge_ndx.dimension(function(d) { return d._id; }), nodeGroup = nodeDimension.group(), edgeGroup = edgeDimension.group(); one_zero_reduce(nodeGroup); one_zero_reduce(edgeGroup); function non_null(group) { return { all: function() { return group.all().filter(function(kv) { return kv.value !== null; }); } }; } var nodeGroup1 = non_null(nodeGroup), edgeGroup1 = non_null(edgeGroup); diagram .nodeDimension(nodeDimension).nodeGroup(nodeGroup1) .edgeDimension(edgeDimension).edgeGroup(edgeGroup1) k(); }); } </script>