This example demonstrates D3.js force directed layout with fixed x-values and a band on the y-axis where source nodes will not be placed. Target nodes are fixed at y = 0.
Color Scheme: http://colorschemedesigner.com/#3q61Uw0w0w0w0
This example demonstrates D3.js force directed layout with fixed x-values and a band on the y-axis where source nodes will not be placed. Target nodes are fixed at y = 0.
Color Scheme: http://colorschemedesigner.com/#3q61Uw0w0w0w0
| @font-face { | |
| font-family:'Oxygen'; | |
| font-style: normal; | |
| font-weight: 400; | |
| src: local('Oxygen'), local('Oxygen-Regular'), url(http://themes.googleusercontent.com/static/fonts/oxygen/v2/RzoNiRR1p2Mqyyz2RwqSMw.woff) format('woff'); | |
| } | |
| @font-face { | |
| font-family:'Oxygen'; | |
| font-style: normal; | |
| font-weight: 700; | |
| src: local('Oxygen Bold'), local('Oxygen-Bold'), url(http://themes.googleusercontent.com/static/fonts/oxygen/v2/yVHpdQrmTj9Kax1tmFSx2j8E0i7KZn-EPnyo3HZu7kw.woff) format('woff'); | |
| } | |
| svg { | |
| } | |
| .axis text { | |
| font-family: Oxygen; | |
| font-size: 10px; | |
| } | |
| .axis line, | |
| .axis path { | |
| fill: none; | |
| stroke: #000; | |
| shape-rendering: crispEdges; | |
| } | |
| .node { | |
| stroke-width: 1.5px; | |
| } | |
| .node.target { | |
| fill: #FFBC73; | |
| stroke: #FFA340; | |
| } | |
| .node.source { | |
| fill: #62B1D0; | |
| stroke: #0776A0; | |
| } | |
| .link { | |
| stroke: #999; | |
| stroke-opacity: .6; | |
| } |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> | |
| <title>SVG Time-Dependent Graph Example - jsFiddle demo by colin_young</title> | |
| <script type='text/javascript' src="http://d3js.org/d3.v3.min.js"></script> | |
| <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
| <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js"></script> | |
| <link rel="stylesheet" type="text/css" href="demo.css"> | |
| </head> | |
| <body> | |
| <div class="graph"></div> | |
| <div id="slider"></div> | |
| <div id="charge"></div> | |
| <script type='text/javascript' src='network.js'></script> | |
| </body> | |
| </html> |
| var lineColor = "#172CAF"; | |
| var circleOutlineColor = "#0776A0"; | |
| var circleFillColor = "#62B1D0"; | |
| var textColorSource = "#FFFFFF"; | |
| var circleOutlineColorTarget = "#FFA340"; | |
| var circleFillColorTarget = "#FFBC73"; | |
| var textColorTarget = "#A65600"; | |
| var nodes = [{ | |
| id : "T0", | |
| name : "Target 0", | |
| type : "t", | |
| time : 0, | |
| strength : 1 | |
| }, { | |
| id : "T1", | |
| name : "Target 1", | |
| type : "t", | |
| time : 3, | |
| strength : 10 | |
| }, { | |
| id : "T2", | |
| name : "Target 2", | |
| type : "t", | |
| time : 5, | |
| strength : 2 | |
| }, { | |
| id : "T3", | |
| name : "Target 3", | |
| type : "t", | |
| time : 8, | |
| strength : 7 | |
| }, { | |
| id : "T4", | |
| name : "Target 4", | |
| type : "t", | |
| time : 6, | |
| strength : 7 | |
| }, { | |
| id : "S1", | |
| name : "Source 1", | |
| type : "s", | |
| time : 1, | |
| count : 2 | |
| }, { | |
| id : "S2", | |
| name : "Source 2", | |
| type : "s", | |
| time : 2, | |
| count : 1 | |
| }, { | |
| id : "S3", | |
| name : "Source 3", | |
| type : "s", | |
| time : 2, | |
| count : 4 | |
| }, { | |
| id : "S4", | |
| name : "Source 4", | |
| type : "s", | |
| time : 4, | |
| count : 2 | |
| }, { | |
| id : "S5", | |
| name : "Source 5", | |
| type : "s", | |
| time : 3, | |
| count : 2 | |
| } | |
| ]; | |
| var links = [{ | |
| source : "S1", | |
| target : "T1", | |
| strength : 0.05 | |
| }, { | |
| source : "S2", | |
| target : "T1", | |
| strength : 0.1 | |
| }, { | |
| source : "S3", | |
| target : "T1", | |
| strength : 0.3 | |
| }, { | |
| source : "S3", | |
| target : "T2", | |
| strength : 0.8 | |
| }, { | |
| source : "S1", | |
| target : "T2", | |
| strength : 0.05 | |
| }, { | |
| source : "S3", | |
| target : "T3", | |
| strength : 1.0 | |
| }, { | |
| source : "S4", | |
| target : "T4", | |
| strength : 1.0 | |
| }, { | |
| source : "S4", | |
| target : "T2", | |
| strength : 0.3 | |
| }, { | |
| source : "S5", | |
| target : "T3", | |
| strength : 1.0 | |
| }, { | |
| source : "S5", | |
| target : "T2", | |
| strength : 0.1 | |
| }, { | |
| source : "S3", | |
| target : "T4", | |
| strength : 1.0 | |
| } | |
| ]; | |
| var margin = { | |
| top : 20, | |
| right : 10, | |
| bottom : 20, | |
| left : 10 | |
| }, | |
| padding = { | |
| top : 60, | |
| right : 60, | |
| bottom : 60, | |
| left : 60 | |
| }, | |
| outerWidth = 500, | |
| outerHeight = 400, | |
| innerWidth = outerWidth - margin.left - margin.right, | |
| innerHeight = outerHeight - margin.top - margin.bottom, | |
| width = innerWidth - padding.left - padding.right, | |
| height = innerHeight - padding.top - padding.bottom, | |
| axisBand = 15; | |
| var x_max = d3.max(nodes, function(d) { return d.time; }); | |
| var x = d3.scale.linear() | |
| .domain([0, x_max]) | |
| .range([0, width]); | |
| var y = d3.scale.linear() | |
| .domain([0, 100]) | |
| .range([0, height]); | |
| var target_axis_position = y(50); | |
| mapNodes = function (nodes) { | |
| var nodesMap; | |
| nodesMap = d3.map(); | |
| nodes.forEach(function (n) { | |
| return nodesMap.set(n.id, n); | |
| }); | |
| return nodesMap; | |
| }; | |
| nodesMap = mapNodes(nodes); | |
| links.forEach(function (l) { | |
| l.source = nodesMap.get(l.source); | |
| l.target = nodesMap.get(l.target); | |
| }); | |
| var color = d3.scale.category20(); | |
| var force = d3.layout.force() | |
| .charge(-240) | |
| .gravity(0.2) | |
| .linkStrength(function (l, i) { | |
| return l.strength; | |
| }) | |
| .size([width, height]); | |
| var svg = d3.select("div.graph").append("svg") | |
| .attr("width", outerWidth) | |
| .attr("height", outerHeight) | |
| .append("g") | |
| .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
| var g = svg.append("g") | |
| .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
| force.nodes(nodes) | |
| .links(links) | |
| .start(); | |
| g.append("rect") | |
| .attr("x", 0) | |
| .attr("y", y(50 - axisBand)) | |
| .attr("width", x(x_max)) | |
| .attr("height", y(2 * axisBand)) | |
| .attr("fill", "#EEE"); | |
| var link = g.selectAll(".link") | |
| .data(links) | |
| .enter().append("line") | |
| .attr("class", "link") | |
| .style("stroke-width", function (d) { | |
| return Math.sqrt(d.strength * 10); | |
| }); | |
| var node = g.selectAll(".node") | |
| .data(nodes) | |
| .enter().append("circle") | |
| .attr("class", "node") | |
| .attr("r", function (d) { | |
| if (d.type == "t") { | |
| return Math.sqrt(d.strength) * 5; | |
| } else if (d.type = "s") { | |
| return Math.sqrt(d.count) * 5; | |
| } else { | |
| return 5; | |
| } | |
| }) | |
| .classed("target", function (d) { | |
| return d.type == "t"; | |
| }) | |
| .classed("source", function (d) { | |
| return d.type == "s"; | |
| }) | |
| .call(force.drag); | |
| node.append("title") | |
| .text(function (d) { | |
| return d.name; | |
| }); | |
| // drag zoom adapted from http://bl.ocks.org/rmarimon/1179647 | |
| var downx = Math.NaN; | |
| var downscalex; | |
| var xAxis = d3.svg.axis() | |
| .scale(x) | |
| .orient("bottom"); | |
| function dragX(d) { | |
| var p = d3.mouse(svg[0][0]); | |
| downx = x.invert(p[0]); | |
| downscalex = x; | |
| }; | |
| g.append("g") | |
| .attr("class", "x axis") | |
| .attr("transform", "translate(0," + target_axis_position + ")") | |
| .call(xAxis) | |
| .on("mousedown", function (d) { dragX(d); }); | |
| svg.select('.x.axis text') | |
| .on("mousedown", function (d) { dragX(d); }); | |
| d3.select('body') | |
| .on("mousemove", function (d) { | |
| if (!isNaN(downx)) { | |
| var p = d3.mouse(svg[0][0]); | |
| var rupx = p[0]; | |
| if (rupx != 0) { | |
| x.domain([downscalex.domain()[0], width * (downx - downscalex.domain()[0]) / rupx + downscalex.domain()[0]]); | |
| } | |
| svg.select('.x.axis').call(xAxis); | |
| force.start(); | |
| } | |
| }) | |
| .on("mouseup", function (d) { | |
| downx = Math.NaN; | |
| }); | |
| var adjust_y = function(d) { | |
| if (d.type == "t") { | |
| return y(50); | |
| } else { | |
| if (Math.abs(y(50) - d.y) < y(axisBand)) { | |
| return d.y < y(50) ? y(50 - axisBand) : y(50 + axisBand); | |
| } else { | |
| return d.y; | |
| } | |
| } | |
| }; | |
| var adjust_x = function(d) { | |
| return x(d.time); | |
| }; | |
| force.on("tick", function () { | |
| link.attr("x1", function (d) { | |
| return adjust_x(d.source); | |
| }) | |
| .attr("y1", function (d) { | |
| return adjust_y(d.source); | |
| }) | |
| .attr("x2", function (d) { | |
| return adjust_x(d.target); | |
| }) | |
| .attr("y2", function (d) { | |
| return adjust_y(d.target); | |
| }); | |
| node.attr("cx", function (d) { | |
| return adjust_x(d); | |
| }) | |
| .attr("cy", function (d) { | |
| return adjust_y(d); | |
| }); | |
| }); | |
| $(function() { | |
| $( "#slider" ).slider({ | |
| range: "min", | |
| value: -240, | |
| min: -960, | |
| max: 0, | |
| slide: function( event, ui ) { | |
| $('#charge').text(ui.value); | |
| force.charge($('#charge').text()).start(); | |
| } | |
| }); | |
| }); |