Skip to content

Instantly share code, notes, and snippets.

@puzzler10
Last active March 18, 2017 22:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save puzzler10/2ce53e7592ef80e164821f26d426f723 to your computer and use it in GitHub Desktop.
Save puzzler10/2ce53e7592ef80e164821f26d426f723 to your computer and use it in GitHub Desktop.
node and link attributes

Here we specify different attributes in the data for links and nodes. We then set the colour of nodes and lines to depend on these attributes.

The characters are from the mesmerising web serial Twig. It's really worth a read!

Want to learn more about node and link attributes? Visit here.

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: black ;
stroke-width: 0px;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
//create somewhere to put the force directed graph
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
//characters
var nodes_data = [
{"name": "Lillian", "sex": "F"},
{"name": "Gordon", "sex": "M"},
{"name": "Sylvester", "sex": "M"},
{"name": "Mary", "sex": "F"},
{"name": "Helen", "sex": "F"},
{"name": "Jamie", "sex": "M"},
{"name": "Jessie", "sex": "F"},
{"name": "Ashton", "sex": "M"},
{"name": "Duncan", "sex": "M"},
{"name": "Evette", "sex": "F"},
{"name": "Mauer", "sex": "M"},
{"name": "Fray", "sex": "F"},
{"name": "Duke", "sex": "M"},
{"name": "Baron", "sex": "M"},
{"name": "Infante", "sex": "M"},
{"name": "Percy", "sex": "M"},
{"name": "Cynthia", "sex": "F"}
]
//Links
//type: A for Ally, E for Enemy
var links_data = [
{"source": "Sylvester", "target": "Gordon", "type":"A" },
{"source": "Sylvester", "target": "Lillian", "type":"A" },
{"source": "Sylvester", "target": "Mary", "type":"A"},
{"source": "Sylvester", "target": "Jamie", "type":"A"},
{"source": "Sylvester", "target": "Jessie", "type":"A"},
{"source": "Sylvester", "target": "Helen", "type":"A"},
{"source": "Helen", "target": "Gordon", "type":"A"},
{"source": "Mary", "target": "Lillian", "type":"A"},
{"source": "Ashton", "target": "Mary", "type":"A"},
{"source": "Duncan", "target": "Jamie", "type":"A"},
{"source": "Gordon", "target": "Jessie", "type":"A"},
{"source": "Sylvester", "target": "Fray", "type":"E"},
{"source": "Fray", "target": "Mauer", "type":"A"},
{"source": "Fray", "target": "Cynthia", "type":"A"},
{"source": "Fray", "target": "Percy", "type":"A"},
{"source": "Percy", "target": "Cynthia", "type":"A"},
{"source": "Infante", "target": "Duke", "type":"A"},
{"source": "Duke", "target": "Gordon", "type":"A"},
{"source": "Duke", "target": "Sylvester", "type":"A"},
{"source": "Baron", "target": "Duke", "type":"A"},
{"source": "Baron", "target": "Sylvester", "type":"E"},
{"source": "Evette", "target": "Sylvester", "type":"E"},
{"source": "Cynthia", "target": "Sylvester", "type":"E"},
{"source": "Cynthia", "target": "Jamie", "type":"E"},
{"source": "Mauer", "target": "Jessie", "type":"E"}
]
//set up the simulation
var simulation = d3.forceSimulation()
//add nodes
.nodes(nodes_data);
//add forces
//we're going to add a charge to each node
//also going to add a centering force
//and a link force
var link_force = d3.forceLink(links_data)
.id(function(d) { return d.name; });
simulation
.force("charge_force", d3.forceManyBody())
.force("center_force", d3.forceCenter(width / 2, height / 2))
.force("links",link_force);
//add tick instructions:
simulation.on("tick", tickActions );
//draw circles for the links
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes_data)
.enter()
.append("circle")
.attr("r", 10)
.attr("fill", circleColour);
//draw lines for the links
var link = svg.append("g")
.attr("class", "links")
.selectAll("line")
.data(links_data)
.enter().append("line")
.attr("stroke-width", 2)
.style("stroke", linkColour);
var drag_handler = d3.drag()
.on("start", drag_start)
.on("drag", drag_drag)
.on("end", drag_end);
//same as u sing .call on the node variable as in https://bl.ocks.org/mbostock/4062045
drag_handler(node)
/** Functions **/
//Function to choose what color circle we have
//Let's return blue for males and red for females
function circleColour(d){
if(d.sex =="M"){
return "blue";
} else {
return "pink";
}
}
//Function to choose the line colour and thickness
//If the link type is "A" return green
//If the link type is "E" return red
function linkColour(d){
if(d.type == "A"){
return "green";
} else {
return "red";
}
}
//drag handler
//d is the node
function drag_start(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function drag_drag(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function drag_end(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
function tickActions() {
//update circle positions each tick of the simulation
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
//update link positions
//simply tells one end of the line to follow one node around
//and the other end of the line to follow the other node around
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; });
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment