I freely admit that this is outrageously geeky. A conversation with folks on twitter led to attempts to try and describe, visually, polyamorous relationships. We kept finding ourselves annotating the links between us, notably with each end of the link, and adding other types of relationships, not all formal or even romantic. This is simply the standard FDL example, with info added about relationship meaning when you hover over the relationship link itself.
Last active
March 2, 2016 05:31
-
-
Save makyo/6754267 to your computer and use it in GitHub Desktop.
Mapping poly relationships with force directed layouts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nodes": | |
[ | |
{"name": "Makyo"}, | |
{"name": "JD"}, | |
{"name": "Forneus"}, | |
{"name": "Des"}, | |
{"name": "Peri"}, | |
{"name": "SQUISH ZONE", | |
"attrs": {"x": -20, "y": -20, "r": 20, "fill": "#888"}}, | |
{"name": "Loomy"}, | |
{"name": "Jake"}, | |
{"name": "Stripes"}, | |
{"name": "Bellua"}, | |
{"name": "Cullen"}, | |
{"name": "Nakita"}, | |
{"name": "Osric"}, | |
{"name": "Bel"}, | |
{"name": "Lunostophiles"}, | |
{"name": "Floe"} | |
], | |
"links": | |
[ | |
{"source": 0, "target": 1, "value": 1, "targetMeaning": "husbandog", | |
"sourceMeaning": "husbandfox", "linkMeaning": "partners, civil union"}, | |
{"source": 0, "target": 2, "value": 2, "targetMeaning": "catfriend", | |
"sourceMeaning": "foxfriend", "linkMeaning": "partners"}, | |
{"source": 2, "target": 3, "value": 1, "targetMeaning": "catfriend", | |
"sourceMeaning": "catfriend", "linkMeaning": "partners"}, | |
{"source": 2, "target": 4, "value": 3, "dashed": true, | |
"linkMeaning": "gender, maybe something"}, | |
{"source": 0, "target": 4, "value": 3, "dashed": true, | |
"linkMeaning": "gender, anxiety, programming"}, | |
{"source": 0, "target": 5, "value": 4, | |
"targetMeaning": "For all those whom I love", | |
"sourceMeaning": "Who knows, really."}, | |
{"source": 1, "target": 6, "value": 4, "dashed": true, | |
"linkMeaning": "Sexuality"}, | |
{"source": 1, "target": 7, "value": 4, "dashed": true, | |
"linkMeaning": "Guns, etc."}, | |
{"source": 7, "target": 8, "value": 1, "linkMeaning": "partners"}, | |
{"source": 4, "target": 9, "value": 1, "linkMeaning": "partners"}, | |
{"source": 0, "target": 10, "value": 3, | |
"linkMeaning": "too alike and too far apart"}, | |
{"source": 0, "target": 11, "value": 4, "dashed": true, | |
"linkMeaning": "roommates, sexually open, close"}, | |
{"source": 1, "target": 11, "value": 4, "dashed": true, | |
"linkMeaning": "roommates, sexually open, close"}, | |
{"source": 0, "target": 12, "value": 4, "dashed": true, | |
"linkMeaning": "sexually open, close"}, | |
{"source": 1, "target": 12, "value": 4, "dashed": true, | |
"linkMeaning": "some other universe, perhaps"}, | |
{"source": 0, "target": 13, "value": 4, "dashed": true, | |
"linkMeaning": "some other universe, perhaps"}, | |
{"source": 1, "target": 13, "value": 4, "dashed": true, | |
"linkMeaning": "sexually open, close"}, | |
{"source": 12, "target": 13, "value": 1, | |
"sourceMeaning": "husband", "targetMeaning": "husband", | |
"linkMeaning": "partners, civil union"}, | |
{"source": 0, "target": 14, "value": 4, "dashed": true, | |
"linkMeaning": "Makers-in-common"}, | |
{"source": 2, "target": 14, "value": 4, "dashed": true, | |
"linkMeaning": "Makers-in-common"}, | |
{"source": 4, "target": 14, "value": 4, "dashed": true, | |
"linkMeaning": "History"}, | |
{"source": 0, "target": 15, "value": 4, "dashed": true, | |
"linkMeaning": "Anxiety, earnestness"} | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.link line { | |
stroke: rgba(0,0,0,0.35); | |
} | |
.link .meaning { | |
fill: #00F; | |
} | |
.node text { | |
pointer-events: none; | |
font: 10px sans-serif; | |
} | |
.hidden { | |
display: none; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var width = 960, | |
height = 500 | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
var force = d3.layout.force() | |
.gravity(.05) | |
.distance(100) | |
.charge(-100) | |
.size([width, height]); | |
d3.json("graph.json", function(error, json) { | |
force | |
.nodes(json.nodes) | |
.links(json.links) | |
.distance(function(d) { return Math.log(d.value * 3) * 50; }) | |
.start(); | |
var link = svg.selectAll(".link") | |
.data(json.links) | |
.enter().append("g") | |
.attr("class", "link"); | |
link.append('text') | |
.attr('class', 'sourceMeaning meaning hidden') | |
.text(function(d) { return d.sourceMeaning }); | |
link.append('text') | |
.attr('class', 'targetMeaning meaning hidden') | |
.text(function(d) { return d.targetMeaning }); | |
link.append('text') | |
.attr('class', 'linkMeaning meaning hidden') | |
.text(function(d) { return d.linkMeaning || ''; }); | |
link.append('line') | |
.attr("stroke-width", function(d) { | |
return 10 / (d.value / 1); | |
}) | |
.attr("stroke-dasharray", function(d) { | |
if (d.dashed) { | |
return "5,5"; | |
} | |
}) | |
.on('mouseover', function(d) { | |
d3.select(this.parentNode).selectAll('.meaning') | |
.classed('hidden', false); | |
}) | |
.on('mouseout', function(d) { | |
d3.select(this.parentNode).selectAll('.meaning') | |
.classed('hidden', true); | |
}); | |
var node = svg.selectAll(".node") | |
.data(json.nodes) | |
.enter().append("g") | |
.attr("class", "node") | |
.call(force.drag); | |
node.append("circle") | |
.attr('x', function(d) { return d.attrs ? d.attrs.x : -10; }) | |
.attr('y', function(d) { return d.attrs ? d.attrs.y : -10; }) | |
.attr('r', function(d) { return d.attrs ? d.attrs.r : 10 }) | |
.attr('fill', function(d) { return d.attrs ? d.attrs.fill : '#000'}); | |
node.append("text") | |
.attr("dx", function(d) { return d.attrs ? d.attrs.r + 2 : 12; }) | |
.attr("dy", ".35em") | |
.text(function(d) { return d.name }); | |
force.on("tick", function() { | |
link.select('line') | |
.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; }); | |
link.select('.sourceMeaning') | |
.attr('dx', function(d) { return d.source.x + 12}) | |
.attr('dy', function(d) { return d.source.y + 24}); | |
link.select('.targetMeaning') | |
.attr('dx', function(d) { return d.target.x + 12}) | |
.attr('dy', function(d) { return d.target.y + 24}); | |
link.select('.linkMeaning') | |
.attr('dx', function(d) { | |
return (d.source.x + ((d.target.x - d.source.x) / 2)); | |
}) | |
.attr('dy', function(d) { | |
return (d.source.y + ((d.target.y - d.source.y) / 2)); | |
}); | |
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); | |
}); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment