Skip to content

Instantly share code, notes, and snippets.

@tomshanley
Last active August 29, 2015 14:01
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 tomshanley/7a9fd25217466b28f575 to your computer and use it in GitHub Desktop.
Save tomshanley/7a9fd25217466b28f575 to your computer and use it in GitHub Desktop.
Capabilities - Stacked to multiple
location capabilitygroup capability assessmentdate totalpeople totalyears
Auckland BA Methodologies Planning and Monitoring Q1 13 20
Auckland BA Methodologies Elicitation Q1 13 25
Auckland BA Methodologies Requirements Management and Communication Q1 13 20
Auckland BA Methodologies Enterprise Analysis Q1 11 30
Auckland BA Methodologies Requirements Analysis Q1 13 10
Auckland BA Methodologies Solution Assessment and Validation Q1 11 31
Auckland BA Methodologies Iterative e.g. RUP Q1 13 41
Auckland BA Methodologies Agile - Scrum Q1 11 20
Auckland BA Methodologies BA Practise Mgmt Q1 7 15
Auckland BA Methodologies Kan Ban Lean Six Sigma Kaizan Q1 10 25
Auckland BA Methodologies Planning and Monitoring Q2 13 44
Auckland BA Methodologies Elicitation Q2 13 19
Auckland BA Methodologies Requirements Management and Communication Q2 13 36
Auckland BA Methodologies Enterprise Analysis Q2 11 30
Auckland BA Methodologies Requirements Analysis Q2 13 42
Auckland BA Methodologies Solution Assessment and Validation Q2 11 31
Auckland BA Methodologies Iterative e.g. RUP Q2 13 35
Auckland BA Methodologies Agile - Scrum Q2 11 20
Auckland BA Methodologies BA Practise Mgmt Q2 7 15
Auckland BA Methodologies Kan Ban Lean Six Sigma Kaizan Q2 10 20
Auckland BA Methodologies Planning and Monitoring Q3 13 42
Auckland BA Methodologies Elicitation Q3 13 38
Auckland BA Methodologies Requirements Management and Communication Q3 13 39
Auckland BA Methodologies Enterprise Analysis Q3 12 33
Auckland BA Methodologies Requirements Analysis Q3 13 39
Auckland BA Methodologies Solution Assessment and Validation Q3 12 34
Auckland BA Methodologies Iterative e.g. RUP Q3 13 24
Auckland BA Methodologies Agile - Scrum Q3 11 20
Auckland BA Methodologies BA Practise Mgmt Q3 7 15
Auckland BA Methodologies Kan Ban Lean Six Sigma Kaizan Q3 11 22
Auckland BA Methodologies Planning and Monitoring Q4 11 39
Auckland BA Methodologies Elicitation Q4 11 37
Auckland BA Methodologies Requirements Management and Communication Q4 11 36
Auckland BA Methodologies Enterprise Analysis Q4 11 30
Auckland BA Methodologies Requirements Analysis Q4 11 36
Auckland BA Methodologies Solution Assessment and Validation Q4 11 31
Auckland BA Methodologies Iterative e.g. RUP Q4 11 25
Auckland BA Methodologies Agile - Scrum Q4 11 20
Auckland BA Methodologies BA Practise Mgmt Q4 11 26
Auckland BA Methodologies Kan Ban Lean Six Sigma Kaizan Q4 11 22
// d3.tip
// Copyright (c) 2013 Justin Palmer
//
// Tooltips for d3.js SVG visualizations
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module with d3 as a dependency.
define(['d3'], factory)
} else {
// Browser global.
root.d3.tip = factory(root.d3)
}
}(this, function (d3) {
// Public - contructs a new tooltip
//
// Returns a tip
return function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
// Public - show the tooltip on the screen
//
// Returns a tip
tip.show = function() {
var args = Array.prototype.slice.call(arguments)
if(args[args.length - 1] instanceof SVGElement) target = args.pop()
var content = html.apply(this, args),
poffset = offset.apply(this, args),
dir = direction.apply(this, args),
nodel = d3.select(node),
i = directions.length,
coords,
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
nodel.html(content)
.style({ opacity: 1, 'pointer-events': 'all' })
while(i--) nodel.classed(directions[i], false)
coords = direction_callbacks.get(dir).apply(this)
nodel.classed(dir, true).style({
top: (coords.top + poffset[0]) + scrollTop + 'px',
left: (coords.left + poffset[1]) + scrollLeft + 'px'
})
return tip
}
// Public - hide the tooltip
//
// Returns a tip
tip.hide = function() {
nodel = d3.select(node)
nodel.style({ opacity: 0, 'pointer-events': 'none' })
return tip
}
// Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
//
// n - name of the attribute
// v - value of the attribute
//
// Returns tip or attribute value
tip.attr = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).attr(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.attr.apply(d3.select(node), args)
}
return tip
}
// Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
//
// n - name of the property
// v - value of the property
//
// Returns tip or style property value
tip.style = function(n, v) {
if (arguments.length < 2 && typeof n === 'string') {
return d3.select(node).style(n)
} else {
var args = Array.prototype.slice.call(arguments)
d3.selection.prototype.style.apply(d3.select(node), args)
}
return tip
}
// Public: Set or get the direction of the tooltip
//
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
// sw(southwest), ne(northeast) or se(southeast)
//
// Returns tip or direction
tip.direction = function(v) {
if (!arguments.length) return direction
direction = v == null ? v : d3.functor(v)
return tip
}
// Public: Sets or gets the offset of the tip
//
// v - Array of [x, y] offset
//
// Returns offset or
tip.offset = function(v) {
if (!arguments.length) return offset
offset = v == null ? v : d3.functor(v)
return tip
}
// Public: sets or gets the html value of the tooltip
//
// v - String value of the tip
//
// Returns html value or tip
tip.html = function(v) {
if (!arguments.length) return html
html = v == null ? v : d3.functor(v)
return tip
}
function d3_tip_direction() { return 'n' }
function d3_tip_offset() { return [0, 0] }
function d3_tip_html() { return ' ' }
var direction_callbacks = d3.map({
n: direction_n,
s: direction_s,
e: direction_e,
w: direction_w,
nw: direction_nw,
ne: direction_ne,
sw: direction_sw,
se: direction_se
}),
directions = direction_callbacks.keys()
function direction_n() {
var bbox = getScreenBBox()
return {
top: bbox.n.y - node.offsetHeight,
left: bbox.n.x - node.offsetWidth / 2
}
}
function direction_s() {
var bbox = getScreenBBox()
return {
top: bbox.s.y,
left: bbox.s.x - node.offsetWidth / 2
}
}
function direction_e() {
var bbox = getScreenBBox()
return {
top: bbox.e.y - node.offsetHeight / 2,
left: bbox.e.x
}
}
function direction_w() {
var bbox = getScreenBBox()
return {
top: bbox.w.y - node.offsetHeight / 2,
left: bbox.w.x - node.offsetWidth
}
}
function direction_nw() {
var bbox = getScreenBBox()
return {
top: bbox.nw.y - node.offsetHeight,
left: bbox.nw.x - node.offsetWidth
}
}
function direction_ne() {
var bbox = getScreenBBox()
return {
top: bbox.ne.y - node.offsetHeight,
left: bbox.ne.x
}
}
function direction_sw() {
var bbox = getScreenBBox()
return {
top: bbox.sw.y,
left: bbox.sw.x - node.offsetWidth
}
}
function direction_se() {
var bbox = getScreenBBox()
return {
top: bbox.se.y,
left: bbox.e.x
}
}
function initNode() {
var node = d3.select(document.createElement('div'))
node.style({
position: 'absolute',
top: 0,
opacity: 0,
'pointer-events': 'none',
'box-sizing': 'border-box'
})
return node.node()
}
function getSVGNode(el) {
el = el.node()
if(el.tagName.toLowerCase() == 'svg')
return el
return el.ownerSVGElement
}
// Private - gets the screen coordinates of a shape
//
// Given a shape on the screen, will return an SVGPoint for the directions
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
// sw(southwest).
//
// +-+-+
// | |
// + +
// | |
// +-+-+
//
// Returns an Object {n, s, e, w, nw, sw, ne, se}
function getScreenBBox() {
var targetel = target || d3.event.target,
bbox = {},
matrix = targetel.getScreenCTM(),
tbbox = targetel.getBBox(),
width = tbbox.width,
height = tbbox.height,
x = tbbox.x,
y = tbbox.y
point.x = x
point.y = y
bbox.nw = point.matrixTransform(matrix)
point.x += width
bbox.ne = point.matrixTransform(matrix)
point.y += height
bbox.se = point.matrixTransform(matrix)
point.x -= width
bbox.sw = point.matrixTransform(matrix)
point.y -= height / 2
bbox.w = point.matrixTransform(matrix)
point.x += width
bbox.e = point.matrixTransform(matrix)
point.x -= width / 2
point.y -= height / 2
bbox.n = point.matrixTransform(matrix)
point.y += height
bbox.s = point.matrixTransform(matrix)
return bbox
}
return tip
};
}));
<!DOCTYPE html>
<meta charset="utf-8">
<link type="text/css" rel="stylesheet" href="tooltip-styles-stackedchart.css">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: white;
background-color: black;
margin: auto;
position: relative;
width: 960px;
}
text {
font: 10px sans-serif;
fill: white;
}
.axis path {
display: none;
}
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.group-label {
font-weight: bold;
text-anchor: end;
}
form {
position: absolute;
right: 10px;
top: 10px;
}
label {
top: 10px;
right: 0px;
}
</style>
<form>
<label><input type="radio" name="mode" value="multiples" checked> Multiples</label>
<label><input type="radio" name="mode" value="stacked"> Stacked</label>
</form>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="d3-tip.js"></script>
<script>
var margin = {top: 10, right: 20, bottom: 20, left: 240},
width = 960 - margin.left - margin.right,
height = 700 - margin.top - margin.bottom;
var y0 = d3.scale.ordinal()
.rangeRoundBands([height, 0], .4);
var y1 = d3.scale.linear();
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1, 0);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var nest = d3.nest()
.key(function(d) { return d.capability; });
var stack = d3.layout.stack()
.values(function(d) { return d.values; })
.x(function(d) { return d.assessmentdate; })
.y(function(d) { return d.totalyears; })
.out(function(d, y0) { d.valueOffset = y0; });
var color = d3.scale.ordinal();
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([0, -195])
.html(function(d) {
return "<strong>Total years:</strong> " + d.totalyears;
})
svg.call(tip);
d3.tsv("ba-skills.tsv", function(error, data) {
data.forEach(function(d) {
d.totalyears = +d.totalyears;
});
var dataByGroup = nest.entries(data);
stack(dataByGroup);
x.domain(dataByGroup[0].values.map(function(d) { return d.assessmentdate; }));
y0.domain(dataByGroup.map(function(d) { return d.key; }));
y1.domain([0, d3.max(data, function(d) { return d.totalyears; })]).range([y0.rangeBand(), 0]);
color
.range(["darkred","red"])
.domain([0, dataByGroup.length - 1]);
/*color
.range(d3.range(dataByGroup.length).map(d3.scale.linear()
.domain([0, dataByGroup.length - 1])
.range(["blue", "red"])
.interpolate(d3.interpolateLab)));*/
/*color
.range(d3.range(dataByGroup.length).map(d3.scale.linear()
.domain([0, dataByGroup.length - 1])
.range(["blue", "red"])
.interpolate(d3.interpolateLab)));*/
var group = svg.selectAll(".group")
.data(dataByGroup)
.enter().append("g")
.attr("class", "group")
.attr("transform", function(d) { return "translate(0," + y0(d.key) + ")"; });
group.append("text")
.attr("class", "group-label")
.attr("x", -6)
.attr("y", function(d) { return y1(d.values[0].totalyears / 2); })
.attr("dy", ".35em")
.text(function(d) { return d.key; });
group.selectAll("rect")
.data(function(d) { return d.values; })
.enter().append("rect")
.attr("class", "bar")
.style("fill", function(d) { return color(d.capability); })
.attr("x", function(d) { return x(d.assessmentdate); })
.attr("y", function(d) { return y1(d.totalyears); })
.attr("width", x.rangeBand())
.attr("height", function(d) { return y0.rangeBand() - y1(d.totalyears); })
.on('mouseover', tip.show)
.on('mouseout', tip.hide);;
group.filter(function(d, i) { return !i; }).append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + y0.rangeBand() + ")")
.call(xAxis);
d3.selectAll("input").on("change", change);
/*var timeout = setTimeout(function() {
d3.select("input[value=\"stacked\"]").property("checked", true).each(change);
}, 2000);*/
function change() {
//clearTimeout(timeout);
if (this.value === "multiples") transitionMultiples();
else transitionStacked();
}
function transitionMultiples() {
var t = svg.transition().duration(750),
g = t.selectAll(".group").attr("transform", function(d) { return "translate(0," + y0(d.key) + ")"; });
g.selectAll("rect").attr("y", function(d) { return y1(d.totalyears); });
g.select(".group-label").attr("y", function(d) { return y1(d.values[0].totalyears / 2); })
}
function transitionStacked() {
var t = svg.transition().duration(750),
g = t.selectAll(".group").attr("transform", "translate(0," + y0(y0.domain()[0]) + ")");
g.selectAll("rect").attr("y", function(d) { return y1(d.totalyears + d.valueOffset); });
g.select(".group-label").attr("y", function(d) { return y1(d.values[0].totalyears / 2 + d.values[0].valueOffset); })
}
});
</script>
/*.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
pointer-events: none;
}*/
.d3-tip {
display: block;
position: absolute;
padding: .5em;
content: attr(title);
min-width: 120px;
text-align: center;
width: auto;
height: auto;
white-space: nowrap;
top: -32px;
background: white;
-moz-border-radius:5px;
-webkit-border-radius:5px;
border-radius:5px;
color: black;
font-size: .86em;
pointer-events: none;
}
/* Eastward tooltips */
.d3-tip.e:after {
content: "\25C0";
margin: -4px 0 0 0;
top: 50%;
left: -8px;
}
/* Southward tooltips */
.d3-tip.s:after {
content: "\25B2";
margin: 0 0 1px 0;
top: -8px;
left: 0;
text-align: center;
}
/* Westward tooltips */
.d3-tip.w:after {
content: "\25B6";
margin: -4px 0 0 -1px;
top: 50%;
left: 100%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment