|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
rect { |
|
fill: none; |
|
border: 1px; |
|
stroke: grey; |
|
pointer-events: all; |
|
} |
|
|
|
.node { |
|
fill: #111; |
|
} |
|
|
|
.cursor { |
|
fill: none; |
|
stroke: brown; |
|
pointer-events: none; |
|
} |
|
|
|
.link { |
|
fill:none; |
|
stroke: #DDD; |
|
stroke-width:0.5px; |
|
} |
|
|
|
.link2 { |
|
stroke: #999; |
|
} |
|
|
|
</style> |
|
<body> |
|
<script src="//d3js.org/d3.v3.min.js"></script> |
|
<script> |
|
|
|
var width = 640, |
|
height = 640; |
|
|
|
var size = 20; |
|
|
|
var fill = d3.scale.category10(); |
|
|
|
var nodes = d3.range( size ).map(function(i) { |
|
return { id: i, x: Math.round(width*Math.random()), y: Math.round(height*Math.random()) }; |
|
}); |
|
|
|
console.log( 'nodes', nodes ); |
|
|
|
var nodeLinks = []; |
|
d3.range( size * 1 ).map(function(i) { |
|
// var isource = Math.round((size-1)*Math.random()); |
|
var isource = i; |
|
|
|
var node = nodes[ isource ]; |
|
console.log( 'isource', node, isource ); |
|
|
|
// d3.range( 5 ).map(function(i) { |
|
// var itarget = Math.round((size-1)*Math.random()); |
|
|
|
// nodeLinks.push({source: nodes[ isource ], target: nodes[ itarget ]}); |
|
// }); |
|
|
|
// add links to any nearby nodes |
|
nodes.forEach(function(target, itarget) { |
|
console.log( 'foreach', target, itarget ); |
|
var x = target.x - node.x, |
|
y = target.y - node.y; |
|
if (isource != itarget && Math.sqrt(x * x + y * y) < 120) { |
|
var existing = nodeLinks.filter( function(d, i) { |
|
console.log( 'filter', d, isource, itarget ); |
|
return ( d.source == itarget && d.target == isource ) |
|
})[0]; |
|
console.log( 'existing?', existing ); |
|
if( existing === undefined ) { nodeLinks.push({source: isource, target: itarget}) }; |
|
} |
|
}); |
|
|
|
}); |
|
|
|
console.log( 'nodeLinks', nodeLinks ); |
|
|
|
var drag = d3.behavior.drag() |
|
.on("drag", function( d, i ) { |
|
d.x += d3.event.dx |
|
d.y += d3.event.dy |
|
d3.select(this).attr("cx", d.x).attr("cy", d.y); |
|
var i = 0; |
|
links.each(function(l, li) { |
|
console.log( l, d, i ); |
|
if (l.source == d.id) { |
|
d3.select(this).attr("x1", d.x).attr("y1", d.y); |
|
} else if (l.target == d.id) { |
|
d3.select(this).attr("x2", d.x).attr("y2", d.y); |
|
} |
|
}); |
|
}); |
|
|
|
var link = d3.svg.line() |
|
.x(function(d) { return d.x; }) |
|
.y(function(d) { return d.y; }) |
|
.interpolate("linear"); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
svg.append("rect") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
// svg.append("path") |
|
// .attr("d", link(nodes) ) |
|
// .attr("class", "link"); |
|
|
|
|
|
// svg.selectAll(".link") |
|
// .data( links ) |
|
// .enter().append("line") |
|
// .attr("class", "link") |
|
// .attr("x1", function( d ) { return d.source.x } ) |
|
// .attr("y1", function( d ) { return d.source.y } ) |
|
// .attr("x2", function( d ) { return d.target.x } ) |
|
// .attr("y2", function( d ) { return d.target.y } ); |
|
|
|
var links = svg.selectAll("link") |
|
.data(nodeLinks) |
|
.enter() |
|
.append("line") |
|
.attr("class", "link") |
|
.attr("x1", function(l) { |
|
var sourceNode = nodes.filter(function(d, i) { |
|
return i == l.source |
|
})[0]; |
|
d3.select(this).attr("y1", sourceNode.y); |
|
return sourceNode.x |
|
}) |
|
.attr("x2", function(l) { |
|
var targetNode = nodes.filter(function(d, i) { |
|
return i == l.target |
|
})[0]; |
|
d3.select(this).attr("y2", targetNode.y); |
|
return targetNode.x |
|
}) |
|
.attr("fill", "none"); |
|
|
|
console.log( links ); |
|
|
|
svg.selectAll(".node") |
|
.data(nodes) |
|
.enter() |
|
.append("circle") |
|
.attr("class", "node") |
|
.attr("r", 4 ) |
|
.attr("cx", function(d) { |
|
return d.x |
|
}) |
|
.attr("cy", function(d) { |
|
return d.y |
|
}) |
|
.style("fill", function(d) { return fill(d.id); }) |
|
.call(drag); |
|
|
|
function transform(d) { |
|
return "translate(" + d.x + "," + d.y + ")"; |
|
} |
|
|
|
|
|
</script> |