Skip to content

Instantly share code, notes, and snippets.

@wbuchanan
Created November 28, 2016 20:38
Show Gist options
  • Save wbuchanan/ba34fadb4c69ffcd006387f06d7b88a8 to your computer and use it in GitHub Desktop.
Save wbuchanan/ba34fadb4c69ffcd006387f06d7b88a8 to your computer and use it in GitHub Desktop.
Balanced Assessment Framework Illustration
// Defines variables that are global in scope. This is good for debugging but not so good for production code
var nodes, links, node,
margin = {top: 20, right: 50, bottom: 20, left: 50},
width = 1200 - margin.right - margin.left,
height = 1080 - margin.top - margin.bottom,
i = 0,
duration = 750,
root,
tree = d3.layout.tree()
.size([width, height])
.separation(function(a, b) { return a.parent == b.parent ? 10 : 10; }),
diagonal = d3.svg.diagonal()
.projection(function(d) { return [ d.x, d.y]; }),
svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json("org.json", function(error, data) {
if (error) console.log(error);
// Assigns the data from the JSON file to the variable root
root = data[0],
// Adds a property to the oldest ancestor node for the horizontal position
root.x0 = 0,
// Adds a property to the oldest ancestor node for the initial vertical position
root.y0 = width / 2;
// Defines a function used to create the collapsing behavior
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
// Collapses all of the data on the eldest ancestor and first child
root.children.forEach(collapse);
// Updates the display
update(root);
});
// Sets the dimensions of the visualization
d3.select(self.frameElement).attr("style", "height:1080; width:650");
// Defines a callback used to update the visualization
function update(source) {
// Compute the new tree layout.
nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 125; });
// Update the nodes…
node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.kind ; });
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.x0 + "," + source.y0 + ")"; })
.on("click", click);
// Adds the circle/node in the diagram
nodeEnter.append("circle")
.attr("r", 5)
.style("fill", "blue")
.style("fill-opacity", function() { return 0.25; });
// Binds the text to the SVG node element
nodeEnter.append("text")
.attr("x", function(d) { return d.children || d._children ? -10 : 10; })
.attr("dy", "2.35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.type + " " + d.name ; })
.style("fill-opacityr", 1)
.call(wrap, 5);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
// Updates the fill of the node during transitions
nodeUpdate.select("circle")
.attr("r", 5)
.style("fill", "blue");
// Updates the opacity of the text during updates
nodeUpdate.select("text").style("fill-opacity", 1).style("font-weight", "bolder");
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.x + "," + source.y + ")"; })
.remove();
// Selects nodes with corresponding radii
nodeExit.select("circle").attr("r", 5);
// Makes text more transparent on exit
nodeExit.select("text")
.style("fill-opacity", function() { return 0.25; });
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.kind ; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
})
.style("opacity", 0.25);
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
// This is the function used to wrap the text displayed with the node elements
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 7.5, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
console.log(tspan.node().getComputedTextLength());
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber + lineHeight + dy + "px").text(word);
}
}
});
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style>
.node {
cursor: pointer;
}
.node box {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #000;
stroke-width: 1.25px;
}
.vertical {
writing-mode:tb-rl;
white-space:nowrap;
display:block;
bottom:0;
width:20px;
height:20px;
font-color: black;
font-weight: bolder;
}
.vertical other {
-webkit-transform:rotate(180deg);
-moz-transform:rotate(180deg);
-o-transform: rotate(180deg);
-ms-transform:rotate(180deg);
transform: rotate(180deg);
}
</style>
</head>
<body>
<script src="balancedAssessment.js"></script>
</body>
</html>
[{
"type" : "Summative",
"name" : "KPREP",
"kind" : "KPREP",
"parent" : "null",
"children" : [{
"type": "Interim",
"name": "Unit Test",
"kind": "Unit 1",
"parent": "Summative",
"children" : [
{
"type": "Formative",
"name": "Home Work 1",
"kind": "HW 1a",
"parent": "Unit 1",
"children": null
},
{
"type": "Formative",
"name": "Home Work 2",
"kind": "HW 2a",
"parent": "Unit 1",
"children": null
},
{
"type": "Formative",
"name": "Home Work 3",
"kind": "HW 3a",
"parent": "Unit 1",
"children": null
},
{
"type": "Formative",
"name": "Home Work 4",
"kind": "HW 4a",
"parent": "Unit 1",
"children": null
},
{
"type": "Formative",
"name": "Class Work 1",
"kind": "CW 1a",
"parent": "Unit 1",
"children": null
},
{
"type": "Formative",
"name": "Group Work 1",
"kind": "GW 2a",
"parent": "Unit 1",
"children": null
}]
},
{
"type": "Interim",
"name": "Common Assessment",
"kind": "Common Assessment",
"parent": "Summative",
"children" : [
{
"type": "Formative",
"name": "Home Work 1",
"kind": "HW 1b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Home Work 2",
"kind": "HW 2b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Home Work 3",
"kind": "HW 3b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Class Work 1",
"kind": "CW 1b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Class Work 2",
"kind": "CW 2b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Class Work 3",
"kind": "CW 3b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Project",
"kind": "Proj 1b",
"parent": "Common Assessment",
"children": null
},
{
"type": "Formative",
"name": "Presentation",
"kind": "Pres 1b",
"parent": "Interim",
"children": null
}]
} ,
{
"type": "Interim",
"name": "MAP",
"kind": "Benchmark",
"parent": "Summative",
"children" : [
{
"type": "Formative",
"name": "Home Work 1",
"kind": "HW 1c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Home Work 2",
"kind": "HW 2c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Home Work 3",
"kind": "HW 3c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Class Work 1",
"kind": "CW 1c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Class Work 2",
"kind": "CW 2c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Class Work 3",
"kind": "CW 3c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Project 1",
"kind": "Proj 1c",
"parent": "Benchmark",
"children": null
},
{
"type": "Formative",
"name": "Project 2",
"kind": "Proj 2c",
"parent": "Benchmark",
"children": null
}]
}
]
}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment