Last active
October 17, 2015 09:17
-
-
Save michaelcolenso/4fe1c66b45136458d8b0 to your computer and use it in GitHub Desktop.
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"> | |
<head> | |
<style> | |
.node { | |
stroke: #000; | |
stroke-width: 1.5px; | |
} | |
.link { | |
stroke: #999; | |
stroke-width: 1.5px; | |
} | |
body { | |
background: #fff; | |
} | |
.node { | |
cursor: pointer; | |
} | |
.node circle { | |
/*fill: #fff; | |
stroke: steelblue;*/ | |
stroke-width: 3px; | |
} | |
.node text { | |
font: 16px sans-serif; | |
fill: #777; | |
} | |
.link { | |
fill: none; | |
stroke: #ccc; | |
stroke-width: 2px; | |
} | |
.tree { | |
margin-bottom: 10px; | |
overflow: auto; | |
} | |
#test .arc2 { | |
stroke-weight: 0.1; | |
fill: #3660b0; | |
} | |
#outer { | |
background: #fff; | |
border-radius: 5px; | |
color: #000; | |
} | |
#div1, | |
#div2, | |
#div3, | |
#div4 { | |
width: 33%; | |
height: auto; | |
box-sizing: border-box; | |
float: left; | |
} | |
#div2 .arc { | |
stroke-weight: 0.1; | |
fill: #f0a417; | |
} | |
#div2 .arc2 { | |
stroke-weight: 0.1; | |
fill: #b00d08; | |
} | |
#div3 .arc { | |
stroke-weight: 0.1; | |
fill: #1d871b; | |
} | |
.selectedRadial { | |
border-radius: 3px; | |
background: #f4f4f4; | |
color: #000; | |
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4); | |
-moz-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4); | |
border: 1px solid rgba(200, 200, 200, 0.85); | |
} | |
.radial { | |
border-radius: 3px; | |
background: #FFFFFF; | |
color: #000; | |
} | |
.background { | |
fill: #FFFFFF; | |
fill-opacity: 1; | |
} | |
.component { | |
fill: #e1e1e1; | |
} | |
.component .label { | |
font-family: Myriad, "Helvetic Neue", Helvetica, Arial; | |
text-anchor: middle; | |
fill: #000; | |
} | |
.arc { | |
stroke-weight: 0.1; | |
fill: #4e8fff; | |
} | |
.arc2 { | |
stroke-weight: 0.1; | |
fill: #3660b0; | |
} | |
.label { | |
font-family: Myriad, "Helvetic Neue", Helvetica, Arial; | |
text-anchor: middle; | |
} | |
.radial-svg { | |
display: block; | |
margin: 0 auto; | |
} | |
</style> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> | |
</head> | |
<body> | |
<div id="forest"> | |
<div id="tree"></div> | |
<div id='outer'> | |
<div id="main"> | |
<div id="div1"></div> | |
<div id="div2"></div> | |
<div id="div3"></div> | |
<div id="div4"></div> | |
</div> | |
</div> | |
</div> | |
<script> | |
//build tree | |
function BuildVerticaLTree(treeData, treeContainerDom) { | |
var margin = { | |
top: 90, | |
right: 120, | |
bottom: 20, | |
left: 120 | |
}; | |
var width = 960 - margin.right - margin.left; | |
var height = 500 - margin.top - margin.bottom; | |
var i = 0; | |
var duration = 1000; | |
var tree = d3.layout.tree() | |
.size([height, width]); | |
var diagonal = d3.svg.diagonal() | |
.projection(function(d) { | |
return [d.x, d.y]; | |
}); | |
var svg = d3.select(treeContainerDom).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 + ")"); | |
root = treeData; | |
update(root); | |
function update(source) { | |
start(); | |
// Compute the new tree layout. | |
var nodes = tree.nodes(root).reverse(), | |
links = tree.links(nodes); | |
// Normalize for fixed-depth. | |
nodes.forEach(function(d) { | |
d.y = d.depth * 100; | |
}); | |
// Declare the nodes… | |
var node = svg.selectAll("g.node") | |
.data(nodes, function(d) { | |
return d.id || (d.id = ++i); | |
}); | |
// Enter the nodes. | |
var nodeEnter = node.enter().append("g") | |
.attr("class", "node") | |
.attr("transform", function(d) { | |
return "translate(" + source.x0 + "," + source.y0 + ")"; | |
}).on("click", nodeclick); | |
nodeEnter.append("circle") | |
.attr("r", 2) | |
.attr("stroke", function(d) { | |
return d.children || d._children ? "steelblue" : "#00c13f"; | |
}) | |
.style("fill", function(d) { | |
return d.children || d._children ? "lightsteelblue" : "#fff"; | |
}); | |
nodeEnter.append("text") | |
.attr("y", function(d) { | |
return d.children || d._children ? -20 : 20; | |
}) | |
.attr("dy", ".39em") | |
.attr("text-anchor", "middle") | |
.text(function(d) { | |
return d.name; | |
}) | |
.style("fill-opacity", "0.1"); | |
// Transition nodes to their new position. | |
//horizontal tree | |
var nodeUpdate = node.transition() | |
.duration(duration) | |
.attr("transform", function(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
}); | |
nodeUpdate.select("circle") | |
.attr("r", 8) | |
.style("fill", function(d) { | |
return d._children ? "lightsteelblue" : "#fff"; | |
}); | |
nodeUpdate.select("text") | |
.style("fill-opacity", .8); | |
// 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(); | |
nodeExit.select("circle") | |
.attr("r", 1e-6); | |
nodeExit.select("text") | |
.style("fill-opacity", 1e-6); | |
// Update the links… | |
// Declare the links… | |
var link = svg.selectAll("path.link") | |
.data(links, function(d) { | |
return d.target.id; | |
}); | |
// Enter the links. | |
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 | |
}); | |
}); | |
// 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 nodeclick(d) { | |
if (d.children) { | |
d._children = d.children; | |
d.children = null; | |
} else { | |
d.children = d._children; | |
d._children = null; | |
} | |
update(d); | |
} | |
} | |
var treeData = { | |
"name": "BELOVED PARENT", | |
"children": [{ | |
"name": "SON", | |
"children": [{ | |
"name": "grandchild", | |
"children": [{ | |
"name": "great-grandchild" | |
}] | |
}, { | |
"name": "grandchild", | |
"children": [] | |
}] | |
}, { | |
"name": "DAUGHTER", | |
"children": [] | |
}] | |
}; | |
BuildVerticaLTree(treeData, "#tree"); | |
}); | |
//tree-built | |
//begin-radial | |
var div1 = d3.select(document.getElementById('div1')); | |
var div2 = d3.select(document.getElementById('div2')); | |
var div3 = d3.select(document.getElementById('div3')); | |
var div4 = d3.select(document.getElementById('div4')); | |
function onClick1() { | |
deselect(); | |
div1.attr("class", "selectedRadial"); | |
} | |
function onClick2() { | |
deselect(); | |
div2.attr("class", "selectedRadial"); | |
} | |
function onClick3() { | |
deselect(); | |
div3.attr("class", "selectedRadial"); | |
} | |
function labelFunction(val, min, max) { | |
} | |
function deselect() { | |
div1.attr("class", "radial"); | |
div2.attr("class", "radial"); | |
div3.attr("class", "radial"); | |
} | |
function start() { | |
var rp1 = radialProgress(document.getElementById('div1')) | |
.label("METRIC") | |
.onClick(onClick1) | |
.diameter(150) | |
.value(78) | |
.render(); | |
var rp2 = radialProgress(document.getElementById('div2')) | |
.label("SYNERGY") | |
.onClick(onClick2) | |
.diameter(150) | |
.value(160) | |
.render(); | |
var rp3 = radialProgress(document.getElementById('div3')) | |
.label("STATISTIC") | |
.onClick(onClick3) | |
.diameter(150) | |
.minValue(100) | |
.maxValue(200) | |
.value(150) | |
.render(); | |
} | |
function radialProgress(parent) { | |
var _data = null, | |
_duration = 700, | |
_selection, | |
_margin = { | |
top: 0, | |
right: 0, | |
bottom: 30, | |
left: 0 | |
}, | |
__width = 300, | |
__height = 300, | |
_diameter, | |
_label = "", | |
_fontSize = 10; | |
var _mouseClick; | |
var _value = 0, | |
_minValue = 0, | |
_maxValue = 100; | |
var _currentArc = 0, | |
_currentArc2 = 0, | |
_currentValue = 0; | |
var _arc = d3.svg.arc() | |
.startAngle(0 * (Math.PI / 180)); //just radians | |
var _arc2 = d3.svg.arc() | |
.startAngle(0 * (Math.PI / 180)) | |
.endAngle(0); //just radians | |
_selection = d3.select(parent); | |
function component() { | |
_selection.each(function(data) { | |
// Select the svg element, if it exists. | |
var svg = d3.select(this).selectAll("svg").data([data]); | |
var enter = svg.enter().append("svg").attr("class", "radial-svg").append("g"); | |
measure(); | |
svg.attr("width", __width) | |
.attr("height", __height); | |
var background = enter.append("g").attr("class", "component") | |
.attr("cursor", "pointer") | |
.on("click", onMouseClick); | |
_arc.endAngle(360 * (Math.PI / 180)) | |
background.append("rect") | |
.attr("class", "background") | |
.attr("width", _width) | |
.attr("height", _height); | |
background.append("path") | |
.attr("transform", "translate(" + _width / 2 + "," + _width / 2 + ")") | |
.attr("d", _arc); | |
background.append("text") | |
.attr("class", "label") | |
.attr("transform", "translate(" + _width / 2 + "," + (_width + _fontSize) + ")") | |
.text(_label); | |
var g = svg.select("g") | |
.attr("transform", "translate(" + _margin.left + "," + _margin.top + ")"); | |
_arc.endAngle(_currentArc); | |
enter.append("g").attr("class", "arcs"); | |
var path = svg.select(".arcs").selectAll(".arc").data(data); | |
path.enter().append("path") | |
.attr("class", "arc") | |
.attr("transform", "translate(" + _width / 2 + "," + _width / 2 + ")") | |
.attr("d", _arc); | |
//Another path in case we exceed 100% | |
var path2 = svg.select(".arcs").selectAll(".arc2").data(data); | |
path2.enter().append("path") | |
.attr("class", "arc2") | |
.attr("transform", "translate(" + _width / 2 + "," + _width / 2 + ")") | |
.attr("d", _arc2); | |
enter.append("g").attr("class", "labels"); | |
var label = svg.select(".labels").selectAll(".label").data(data); | |
label.enter().append("text") | |
.attr("class", "label") | |
.attr("y", _width / 2 + _fontSize / 3) | |
.attr("x", _width / 2) | |
.attr("cursor", "pointer") | |
.attr("width", _width) | |
.text(function(d) { | |
return Math.round((_value - _minValue) / (_maxValue - _minValue) * 100) + "%" | |
}) | |
.style("font-size", _fontSize + "px") | |
.on("click", onMouseClick); | |
path.exit().transition().duration(500).attr("x", 1000).remove(); | |
layout(svg); | |
function layout(svg) { | |
var ratio = (_value - _minValue) / (_maxValue - _minValue); | |
var endAngle = Math.min(360 * ratio, 360); | |
endAngle = endAngle * Math.PI / 180; | |
path.datum(endAngle); | |
path.transition().duration(_duration) | |
.attrTween("d", arcTween); | |
if (ratio > 1) { | |
path2.datum(Math.min(360 * (ratio - 1), 360) * Math.PI / 180); | |
path2.transition().delay(_duration).duration(_duration) | |
.attrTween("d", arcTween2); | |
} | |
label.datum(Math.round(ratio * 100)); | |
label.transition().duration(_duration) | |
.tween("text", labelTween); | |
} | |
}); | |
function onMouseClick(d) { | |
if (typeof _mouseClick == "function") { | |
_mouseClick.call(); | |
} | |
} | |
} | |
function labelTween(a) { | |
var i = d3.interpolate(_currentValue, a); | |
_currentValue = i(0); | |
return function(t) { | |
_currentValue = i(t); | |
this.textContent = Math.round(i(t)) + "%"; | |
} | |
} | |
function arcTween(a) { | |
var i = d3.interpolate(_currentArc, a); | |
return function(t) { | |
_currentArc = i(t); | |
return _arc.endAngle(i(t))(); | |
}; | |
} | |
function arcTween2(a) { | |
var i = d3.interpolate(_currentArc2, a); | |
return function(t) { | |
return _arc2.endAngle(i(t))(); | |
}; | |
} | |
function measure() { | |
_width = _diameter - _margin.right - _margin.left - _margin.top - _margin.bottom; | |
_height = _width; | |
_fontSize = _width * .2; | |
_arc.outerRadius(_width / 2); | |
_arc.innerRadius(_width / 2 * .85); | |
_arc2.outerRadius(_width / 2 * .85); | |
_arc2.innerRadius(_width / 2 * .85 - (_width / 2 * .15)); | |
} | |
component.render = function() { | |
measure(); | |
component(); | |
return component; | |
} | |
component.value = function(_) { | |
if (!arguments.length) return _value; | |
_value = [_]; | |
_selection.datum([_value]); | |
return component; | |
} | |
component.margin = function(_) { | |
if (!arguments.length) return _margin; | |
_margin = _; | |
return component; | |
}; | |
component.diameter = function(_) { | |
if (!arguments.length) return _diameter | |
_diameter = _; | |
return component; | |
}; | |
component.minValue = function(_) { | |
if (!arguments.length) return _minValue; | |
_minValue = _; | |
return component; | |
}; | |
component.maxValue = function(_) { | |
if (!arguments.length) return _maxValue; | |
_maxValue = _; | |
return component; | |
}; | |
component.label = function(_) { | |
if (!arguments.length) return _label; | |
_label = _; | |
return component; | |
}; | |
component._duration = function(_) { | |
if (!arguments.length) return _duration; | |
_duration = _; | |
return component; | |
}; | |
component.onClick = function(_) { | |
if (!arguments.length) return _mouseClick; | |
_mouseClick = _; | |
return component; | |
} | |
return component; | |
//end-radial | |
</script> | |
</body> | |
</html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment