Skip to content

Instantly share code, notes, and snippets.

@sundorf
Created November 20, 2012 14:51
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 sundorf/4118379 to your computer and use it in GitHub Desktop.
Save sundorf/4118379 to your computer and use it in GitHub Desktop.
Pyramid with D3 and Angular
angular.module('members',
[ 'd3Charts']).config(
[ '$routeProvider', function($routeProvider) {
$routeProvider.when('/dashboard', {
templateUrl : 'assets/html/members/dashboard.html',
controller : DashboardCtrl
});
} ]);
function DashboardCtrl($scope) {
$scope.generate = function () {
var dataRange = 20;
var dataGrouped = [];
for ( var i = 100; i > 0; i-=10) {
dataGrouped.push({sharedLabel: i-10 + "-" + i, barData1: Math.random() * dataRange, barData2: Math.random() * dataRange});
}
$scope.dataGrouped = dataGrouped;
var data = [];
for ( var i = 100; i > 0; i-=1) {
data.push({sharedLabel: i, barData1: Math.random() * dataRange, barData2: Math.random() * dataRange});
}
$scope.data = data;
};
$scope.generate();
}
var d3Charts = angular.module('d3Charts', []);
//http://www.jasondavies.com/d3-pyramid/
//http://btford.github.com/angular-d3-demo/
d3Charts.directive('pyramid', function() {
var w = 300,
h = 200,
topMargin = 15,
labelSpace = 30,
outerMargin = 15,
gap = 2,
leftLabel = "Feminino",
rightLabel = "Masculino";
return {
restrict : 'C',
scope : {
data : '=',
width : '=',
height : '=',
},
link : function(scope, element, attrs) {
if(scope.width) w = scope.width;
if(scope.height) h = scope.height;
innerMargin = w/2+labelSpace;
if(attrs.leftLabel) leftLabel = attrs.leftLabel;
if(attrs.rightLabel) rightLabel = attrs.rightLabel;
var vis = d3.select(element[0]).append("svg").attr("width", w).attr("height", h);
var commas = d3.format(",.0f");
scope.$watch('data', function (newVal, oldVal) {
data = newVal;
dataRange = d3.max(data.map(function(d) { return Math.max(d.barData1, d.barData2) }));
refresh(data);
});
function refresh(data) {
var chartWidth = w - innerMargin - outerMargin,
barWidth = h / data.length,
yScale = d3.scale.linear().domain([0, data.length]).range([0, h-topMargin]),
total = d3.scale.linear().domain([0, dataRange]).range([0, chartWidth - labelSpace]);
vis.selectAll('*').remove();
/* barData1 label */
vis.append("text").attr("class", "label").text(leftLabel).attr("x",
w - innerMargin).attr("y", topMargin - 3).attr("text-anchor", "end");
/* barData2 label */
vis.append("text").attr("class", "label").text(rightLabel).attr("x",
innerMargin).attr("y", topMargin - 3);
/* female bars and data labels */
var bar = vis.selectAll("g.bar").data(data).enter().append("g").attr(
"class", "bar").attr("transform", function(d, i) {
return "translate(0," + (yScale(i) + topMargin) + ")";
});
var wholebar = bar.append("rect").attr("width", w).attr("height",
barWidth - gap).attr("fill", "none").attr("pointer-events", "all");
var highlight = function(c) {
return function(d, i) {
bar.filter(function(d, j) {
return i === j;
}).attr("class", c);
};
};
bar.on("mouseover", highlight("highlight bar")).on("mouseout",
highlight("bar"));
bar.append("rect").attr("class", "femalebar").attr("height",
barWidth - gap)
.attr("rx", "5").attr("ry", "5");
bar.append("text").attr("class", "femalebar").attr("dx", -3).attr("dy",
"1em").attr("text-anchor", "end");
bar.append("rect").attr("class", "malebar")
.attr("height", barWidth - gap).attr("x", innerMargin)
.attr("rx", "5").attr("ry", "5");
bar.append("text").attr("class", "malebar").attr("dx", 3).attr("dy",
"1em");
/* sharedLabels */
bar.append("text").attr("class", "shared").attr("x", w / 2).attr("dy",
"1em").attr("text-anchor", "middle").text(function(d) {
return d.sharedLabel;
});
var bars = d3.selectAll("g.bar").data(data);
bars.selectAll("rect.malebar").transition().attr("width", function(d) {
return total(d.barData1);
});
bars.selectAll("rect.femalebar").transition().attr("x", function(d) {
return innerMargin - total(d.barData2) - 2 * labelSpace;
}).attr("width", function(d) {
return total(d.barData2);
});
bars.selectAll("text.malebar").text(function(d) {
return commas(d.barData1);
}).transition().attr("x", function(d) {
return innerMargin + total(d.barData1);
});
bars.selectAll("text.femalebar").text(function(d) {
return commas(d.barData2);
}).transition().attr("x", function(d) {
return innerMargin - total(d.barData2) - 2 * labelSpace;
});
}
}
}
});
<h1>Dashboard</h1>
<div name="a" class="pyramid" data="dataGrouped"></div>
<div name="b" class="pyramid" data="data" width="500" height="1500"></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment