This is a six part series, taking you through stages of designing and creating reusable visualizations with d3.js
All visualizations have the same functionality, showcase the individual points with a bar chart and sum up the selected bars.
Part 3. This is showcasing the power of combining Angular.js with d3.js and how to bind them together creating an abstraction between the visualization (the bar chart) and the rest of the application.
These are examples created for a talk (slides and video).
Cheers,
Miles @milr0c
xxxxxxxxxx
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="https://littlesparkvt.com/flatstrap/assets/css/bootstrap.css"/>
<link type="text/css" rel="stylesheet" href="style.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="src.js"></script>
</head>
<body>
<div ng-app="main">
<div ng-controller="MainController">
<div class="row">
<div class="span2">
<button class="btn btn-success" ng-click="update()">update</button>
</div>
<div class="span2" id="sum">
TOTAL: {{sum}}
</div>
</div>
<chart-bar data="data" summed="summed(args)"></chart-bar>
</div>
</div>
<script type="text/javascript">
var main = angular.module('main', [])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', { controller: MainController });
}]);
// Controllers
var MainController = ['$scope', function($scope) {
$scope.randomize = function(n, y) {
if (arguments.length < 2) y = 400;
if (!arguments.length) n = 20;
var i = 0;
return d3.range(~~(Math.random()*n) + 1).map(function(d, i) { return {
x: ++i,
y: ~~(Math.random()*y)
}});
};
$scope.update = function() {
$scope.data = $scope.randomize();
$scope.sum = 0;
};
$scope.summed = function() {
// there has to be a better way to pass variables,
// still learning angular
var extent = arguments[0][0],
x = arguments[0][1],
l = $scope.data.length;
$scope.sum = 0;
for (var i = 0; i < l; i++) {
var d = $scope.data[i];
if (extent[0] <= x(d.x) && x(d.x) + x.rangeBand() <= extent[1]) {
$scope.sum += d.y;
}
}
$scope.$apply();
};
// Models
$scope.sum = 0;
$scope.data = $scope.randomize();
}];
// Views
main.directive('chartBar', function() {
var bar = charts.bar();
return {
restrict: 'E',
replace: true,
template: '<div class="chart"></div>',
scope: {
data: '=',
// barebone for now
summed: '&'
},
link: function($scope, $element, $attr) {
var div = d3.select($element[0]);
bar.on('brush', function() {
var extent = d3.event.target.extent(),
x = bar.x();
$scope.summed({args:[extent, x]});
});
bar.on('brushend', function() {
var extent = d3.event.target.extent(),
x = bar.x();
$scope.summed({args:[extent, x]});
});
$scope.$watch('data', function(newVal, oldVal) {
if(newVal) div.datum(newVal).call(bar);
});
}
}
});
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js
https://d3js.org/d3.v3.min.js