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(); | |
} | |
}); | |
}); |