Last active
August 29, 2015 14:15
-
-
Save matt-bernhardt/b91e72e6f1667e865b7e to your computer and use it in GitHub Desktop.
Combination of list items
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
svg { | |
font: 10px sans-serif; | |
} | |
.cell, | |
.label { | |
opacity: 0.5; | |
} | |
.cell:hover, | |
.label:hover { | |
opacity: 1; | |
} | |
/* | |
svg text { | |
font-size: 20px; | |
} | |
*/ | |
.active { | |
opacity: 1; | |
} |
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
// Basic parameters | |
var i; // counters | |
var _s32 = (Math.sqrt(3)/2); // constant ratio of hexagon's internal to external radius | |
var nodeSize = 40; // size of an individual node - this may become auto calculated | |
var nodeText = 12; | |
// need to add a label size bsaed on data label lengths | |
var dx = nodeSize * 1.5; // column spacing value | |
var dy = nodeSize * _s32; // row spacing value | |
var w = 800; // total plot width | |
var h = 500; // total plot height | |
// need to refactor the margin calculations... | |
var margin = { // this is meant to provide a margin around the plot | |
top: nodeSize, | |
right: nodeSize * 1.5, | |
bottom: nodeSize * 1.5, | |
left: 200 | |
}; | |
var svgContainer; // overall plot container | |
var label, labels, labelText; // plot labels | |
var hexagon, hexagons; // plot data appears in hexagons | |
// create container | |
svgContainer = d3.select("#combinations") | |
.append("svg") | |
.attr("width", w) | |
.attr("height", h); | |
// load data, build visualization | |
d3.json("combinations.json", function(error, data) { | |
if(error) { | |
alert("Error loading json file:\n" + error.statusText); | |
console.log(error); | |
} else { | |
// build node labels | |
buildLabels(data.nodes); | |
// draw hexagon grid | |
buildHexagons(data.combinations); | |
buildListeners(); | |
} | |
}); | |
// Functions | |
buildHexagons = function(data) { | |
hexagons = svgContainer.append("g") | |
.attr("class","hexagons"); | |
hexagon = hexagons.selectAll("path") | |
.data(data) | |
.enter() | |
.append("path") | |
.attr("data-combination",function(d,i) { | |
return d.source+" "+d.target; | |
}) | |
.style("fill", "rgba(255,192,192,0.5)") | |
.attr("stroke","rgb(64,64,64)") | |
.attr("d", function(d,i) { | |
col = margin.left + ( Math.abs(d.source - d.target) * dx ); | |
row = ((Math.abs(d.source-d.target)/2) + Math.min(d.source,d.target)) * Math.sqrt(3) * nodeSize + margin.top; | |
return setHexagonPoints(col,row,nodeSize); | |
}) | |
.attr("class","cell"); | |
}; | |
buildLabels = function(data) { | |
labels = svgContainer.append("g") | |
.attr("class","labels"); | |
labelText = labels.selectAll("g text") | |
.data(data) | |
.enter() | |
.append("text") | |
.attr("x",nodeText) | |
.attr("y",function(d,i){ | |
return (i*dy*2) + dy + nodeText/2; | |
}) | |
.attr("font-size",nodeText ) | |
.text(function(d) { | |
return d.name; | |
}); // label text | |
label = labels.selectAll("path") | |
.data(data) | |
.enter() | |
.append("path") // label drawing | |
.style("fill", "rgba(255,192,192,0.5)") | |
.attr("stroke","rgb(64,64,64)") | |
.attr("class","label") | |
.attr("data-node",function(d,i){ | |
return i; | |
}) | |
.attr("d",function(d,i) { | |
var startY = i * nodeSize*_s32*2 + (margin.top - nodeSize*_s32); | |
var path = "M 0 " + startY + " "; | |
path += "H " + (margin.left + dx - nodeSize) + " "; | |
path += "L " + (margin.left + dx - nodeSize/2) + " " + (startY + ( _s32*nodeSize ) ) + " "; | |
path += "L " + (margin.left + dx - nodeSize) + " " + (startY + ( _s32*nodeSize * 2) ) + " "; | |
path += "H 0 "; | |
return path; | |
}); | |
}; | |
buildListeners = function() { | |
$("g.hexagons path").mouseout(function() { | |
// reset all labels | |
$("g.labels").children("path").each(function() { | |
$(this).attr("class","label"); | |
}); | |
}); | |
$("g.labels path").mouseout(function() { | |
// reset all labels | |
$("g.hexagons").children("path").each(function() { | |
$(this).attr("class","cell"); | |
}); | |
}); | |
$("g.hexagons path").mouseover(function() { | |
// highlight the labels for the relevant combined node | |
var cl = $(this).data("combination").split(" ").sort(); | |
for(var x in cl){ | |
// cl[x] = +cl[x]; | |
var needle = $("g.labels").children("path")[+cl[x]]; | |
$(needle).attr("class","label active"); | |
} | |
}); | |
$("g.labels path").mouseover(function() { | |
// highlight the labels for the relevant combined node | |
var needle = $(this).data("node"); | |
var haystack = $("g.hexagons path"); | |
console.log(haystack); | |
for (var x = 0; x < haystack.length; x++) { | |
var candidate = haystack[x].attributes["data-combination"].value.split(" ").map(Number); | |
console.log(needle); | |
console.log(candidate); | |
console.log(typeof(candidate)); | |
// need to be able to read the candidate's data-combination attribute | |
if(candidate.indexOf(needle) >= 0) { | |
console.log("found"); | |
haystack[x].attributes["class"].value = "cell active"; | |
} else { | |
console.log("not here"); | |
haystack[x].attributes["class"].value = "cell"; | |
} | |
console.log(""); | |
} | |
}); | |
}; | |
setHexagonPoints = function(x,y,size) { | |
var hexPoints = ""; | |
hexPoints += "M " + (size + x ) + " " + (0 + y ) + " "; | |
hexPoints += "L " + (size/2 + x ) + " " + (size*_s32 + y ) + " " ; | |
hexPoints += "L " + (-size/2 + x) + " " + (size*_s32 + y ) + " " ; | |
hexPoints += "L " + (-size + x ) + " " + (0 + y ) + " " ; | |
hexPoints += "L " + (-size/2 + x) + " " + (-size*_s32 + y) + " " ; | |
hexPoints += "L " + (size/2 + x ) + " " + (-size*_s32 + y) + " " ; | |
hexPoints += "L " + (size + x ) + " " + (0 + y ) + " " ; | |
return hexPoints; | |
}; | |
/* | |
setLabelShape = function(x,y,size) { | |
var labelPoints = []; | |
labelPoints.push([0 , 0 ]); | |
labelPoints.push([size/2 + x , 0 ]); | |
labelPoints.push([size + x , _s32*size / 2 ]); | |
labelPoints.push([size/2 + x , _s32*size ]); | |
labelPoints.push([0 , _s32*size ]); | |
return labelPoints; | |
}; | |
*/ |
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":"Architecture + Planning"}, | |
{"name":"Engineering"}, | |
{"name":"Humanities, Arts, and Social Sciences"}, | |
{"name":"Management"}, | |
{"name":"Science"} | |
], | |
"combinations":[ | |
{"source":0,"target":1,"value":1}, | |
{"source":0,"target":2,"value":2}, | |
{"source":0,"target":3,"value":3}, | |
{"source":0,"target":4,"value":4}, | |
{"source":1,"target":2,"value":5}, | |
{"source":1,"target":3,"value":6}, | |
{"source":1,"target":4,"value":7}, | |
{"source":2,"target":3,"value":8}, | |
{"source":2,"target":4,"value":9}, | |
{"source":3,"target":4,"value":10} | |
] | |
} |
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> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html;charset=utf-8"> | |
<title>Node Combinations Graph</title> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" charset="utf-8"></script> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<link href="combinations.css" rel="stylesheet" type='text/css' /> | |
</head> | |
<body> | |
<div id="combinations"></div> | |
<script src="combinations.js" charset="utf-8"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment