Created
January 10, 2016 03:08
-
-
Save kneerunjun/430c947b69bd9e172d85 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
(function () { | |
var skilllevelsPlot = angular.module("skillmaze").directive("skilllevelsPlot", function () { | |
return { | |
restrict: "E", | |
scope: { | |
data: "=" | |
}, | |
link: function (scope, elem, attrs) { | |
var maxWidth = 800; | |
var maxHeight = 300; | |
var svg = d3.select(elem[0]).append("svg").attr({ | |
width: maxWidth, | |
height: maxHeight, | |
"class": "canvas" | |
}).style({ | |
"border": "#1abc9c solid 0px" | |
}) | |
var plot = function () { | |
d3.select(".canvas").append("g").attr({ "class": "plot" }); | |
} | |
var unPlot = function () { | |
d3.select(".canvas .plot").remove(); | |
} | |
var refresh = function () { | |
//this is where can draw the graph in the entirety | |
unPlot(); | |
plot(); | |
var xExtent = [20, maxWidth - 10]; | |
var yExtent = [20, maxHeight - 30]; | |
var skillNested = d3.nest().key(function (d) { | |
return d.skill.title; | |
}).entries(scope.data); | |
var outerPadding = function (padding) { | |
var maxCategories = 5; | |
var extent = xExtent[1] - xExtent[0]; //overall length | |
// (2*op)+[(n-1)*p]*rangeBandWidth + (n*rangeBandWidth) =extent | |
// for the snug fit condition we are assuming that there is no outer padding | |
var rangeBandWidth = extent / ((1 + padding) * maxCategories - padding); //this is the snugfit | |
/*above denotes the rangebandwidth when you have no outerpadding and with internal padding as 'padding' you are able still fit all the bars in the given width*/ | |
/*the padding that is sent in as a parameter is basically the internal padding */ | |
/*1>padding value>0*/ | |
//getting the rangeBand width that snug fits all the categories with no outerpadding | |
var n = d3.nest().key(function (d) { | |
return d.skill.title; | |
}).entries(scope.data).map(function (d) { | |
return d.key; | |
}).length; | |
console.log("the rangebandwidth is: " + rangeBandWidth); | |
var op = ((extent - (n * rangeBandWidth) - ((n - 1) * padding * rangeBandWidth)) / 2); | |
var percentOp = op / rangeBandWidth;//calculating the percentage of the outer padding in terms of rangeBandwithd | |
console.log("outer padding is: " + percentOp); | |
return percentOp; | |
} | |
var xScale = d3.scale.ordinal().domain(skillNested.map(function (d) { | |
return d.key; | |
})).rangeRoundBands(xExtent, 0.2, outerPadding(0.2)); | |
var rolledup = d3.nest().key(function (d) { | |
return d.skill.title; | |
}).key(function (d) { | |
return d.level; | |
}).rollup(function (emps) { | |
return { count: emps.length } | |
}).entries(scope.data); | |
//{key: ".NET", values :[{key: "Sensei", count:1}, {key: "Master", count:2},... ]} | |
//this is the format of the data that we get from rolling up the data | |
//to make it more legible, here is what we can do now. . | |
//mapping the array to a better named array | |
var mapped = rolledup.map(function (d) { | |
return { | |
skill: d.key, rollup: d.values.map(function (e) { | |
return { level: e.key, count: e.values.count }; | |
}) | |
}; | |
}); | |
//{skill:".NET", rollup:[{level:"Sensei", count:1},{level:"Master", count:2}, ...]} | |
//this is much better to read | |
var yScale = d3.scale.linear().domain([ | |
d3.max(mapped.map(function (d) { | |
return d3.max(d.rollup, function (e) { | |
return e.count; | |
}); | |
})),0]).range(yExtent); | |
//plotting the xaxis | |
var xAxis = d3.select(".canvas .plot").append("g").attr({ "class": "axes" }).append("g").attr({ "class": "xaxis" }) | |
.call(d3.svg.axis().scale(xScale).orient("bottom").ticks(skillNested.map(function (d) { | |
return d.key | |
}).length).tickSize(10)); | |
d3.select(".canvas .plot .axes .xaxis path").style({ "fill": "none", "stroke": "#ecf0f1", "stroke-width": "1px" }); | |
d3.selectAll(".canvas .plot .axes .xaxis .tick line").style({ "fill": "none", "stroke": "#ecf0f1", "stroke-width": "1px" }); | |
d3.selectAll(".canvas .plot .axes .xaxis .tick text").style({ "fill": "#ecf0f1" }); | |
d3.select("g.xaxis").attr("transform", "translate(0," + yExtent[1] + ")"); | |
//plotting the yaxis | |
var yAxis = d3.select(".canvas .plot g.axes").append("g").attr({ "class": "yaxis" }) | |
.call(d3.svg.axis().scale(yScale).orient("left").ticks(10).tickSize(xExtent[1]-20).tickFormat(d3.format("d"))); | |
d3.select(".canvas .plot .axes .yaxis path").style({ "fill": "none", "stroke": "#ecf0f1", "stroke-width": "1px" }); | |
d3.selectAll(".canvas .plot .axes .yaxis .tick line").style({ "fill": "none", "stroke": "#ecf0f1", "stroke-width": "1px" }); | |
d3.selectAll(".canvas .plot .axes .yaxis .tick text").style({ "fill": "#ecf0f1" }); | |
d3.select("g.yaxis").attr("transform", "translate(" + xExtent[1] + ",0)"); | |
//plotting the rectangles .. | |
var columns = d3.select(".canvas .plot").append("g").attr("class", "columns"); | |
//lets have groups for each of the skills .. translated by the skill distance on the x axis | |
var barWidth = 25; | |
var clrScale = d3.scale.ordinal().domain(d3.nest().key(function (d) { | |
return d.level; | |
}).entries(scope.data).map(function (d) { | |
return d.key; | |
})).range(["#e74c3c", "#e67e22", "#f1c40f", "#16a085", "#27ae60"]); | |
var skillGroups = d3.select(".canvas .plot g.columns").selectAll("g").data(mapped).enter().append("g").attr({ | |
"transform": function (d) { return "translate(" + xScale(d.skill) + ",0)"; }, | |
"class": function (d) { | |
return d.skill; | |
} | |
}).selectAll("rect").data(function (d) { | |
return d.rollup; | |
}).enter().append("rect").attr({ | |
width: barWidth, | |
height: 0, | |
y: yExtent[1], | |
x: function (d,i) { | |
return i * barWidth; | |
}, | |
}).style({ | |
"fill": function (d) { | |
return clrScale(d.level); | |
} | |
}) | |
.transition().duration(1700) | |
.attr({ | |
height: function (d) { return yExtent[1] - yScale(d.count); }, | |
y: function (d) { | |
return yScale(d.count); | |
}, | |
}); | |
} | |
scope.$watch("data", function (newValue, oldValue) { | |
refresh(); | |
}) | |
} | |
} | |
}) | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment