This is a code excerpt from the book D3 on Angular. http://leanpub.com/d3angularjs
The data was scraped from Wikipedia on 3/15/2014: https://en.wikipedia.org/wiki/List_of_The_Walking_Dead_episodes
This is a code excerpt from the book D3 on Angular. http://leanpub.com/d3angularjs
The data was scraped from Wikipedia on 3/15/2014: https://en.wikipedia.org/wiki/List_of_The_Walking_Dead_episodes
season | title | directed_by | written_by | air_date | us_viewers | |
---|---|---|---|---|---|---|
1 | Days Gone Bye | Frank Darabont | Teleplay by: Frank Darabont | 2010-10-31 | 5.35 | |
1 | Guts | Michelle MacLaren | Frank Darabont | 2010-11-07 | 4.71 | |
1 | Tell It to the Frogs | Gwyneth Horder-Payton | Story by: Charles H. Eglee & Jack LoGiudice Teleplay by: Charles H. Eglee & Jack LoGiudice and Frank Darabont | 2010-11-14 | 5.07 | |
1 | Vatos | Johan Renck | Robert Kirkman | 2010-11-21 | 4.75 | |
1 | Wildfire | Ernest Dickerson | Glen Mazzara | 2010-11-28 | 5.56 | |
1 | TS-19 | Guy Ferland | Adam Fierro and Frank Darabont | 2010-12-05 | 5.97 | |
2 | What Lies Ahead | Ernest Dickerson & Gwyneth Horder-Payton | Ardeth Bey and Robert Kirkman | 2011-10-16 | 7.26 | |
2 | Bloodletting | Ernest Dickerson | Glen Mazzara | 2011-10-23 | 6.70 | |
2 | Save the Last One | Phil Abraham | Scott M. Gimple | 2011-10-30 | 6.10 | |
2 | Cherokee Rose | Billy Gierhart | Evan Reilly | 2011-11-06 | 6.29 | |
2 | Chupacabra | Guy Ferland | David Leslie Johnson | 2011-11-13 | 6.12 | |
2 | Secrets | David Boyd | Angela Kang | 2011-11-20 | 6.08 | |
2 | Pretty Much Dead Already | Michelle MacLaren | Scott M. Gimple | 2011-11-27 | 6.62 | |
2 | Nebraska | Clark Johnson | Evan Reilly | 2012-02-12 | 8.10 | |
2 | Triggerfinger | Billy Gierhart | David Leslie Johnson | 2012-02-19 | 6.89 | |
2 | 18 Miles Out | Ernest Dickerson | Scott M. Gimple & Glen Mazzara | 2012-02-26 | 7.04 | |
2 | Judge, Jury, Executioner | Greg Nicotero | Angela Kang | 2012-03-04 | 6.77 | |
2 | Better Angels | Guy Ferland | Evan Reilly & Glen Mazzara | 2012-03-11 | 6.89 | |
2 | Beside the Dying Fire | Ernest Dickerson | Robert Kirkman & Glen Mazzara | 2012-03-18 | 8.99 | |
3 | Seed | Ernest Dickerson | Glen Mazzara | 2012-10-14 | 10.87 | |
3 | Sick | Billy Gierhart | Nichole Beattie | 2012-10-21 | 9.55 | |
3 | Walk with Me | Guy Ferland | Evan Reilly | 2012-10-28 | 10.51 | |
3 | Killer Within | Guy Ferland | Sang Kyu Kim | 2012-11-04 | 9.27 | |
3 | Say the Word | Greg Nicotero | Angela Kang | 2012-11-11 | 10.37 | |
3 | Hounded | Dan Attias | Scott M. Gimple | 2012-11-18 | 9.21 | |
3 | When the Dead Come Knocking | Dan Sackheim | Frank Renzulli | 2012-11-25 | 10.43 | |
3 | Made to Suffer | Billy Gierhart | Robert Kirkman | 2012-12-02 | 10.48 | |
3 | The Suicide King | Lesli Linka Glatter | Evan Reilly | 2013-02-10 | 12.26 | |
3 | Home | Seith Mann | Nichole Beattie | 2013-02-17 | 11.05 | |
3 | I Ain't a Judas | Greg Nicotero | Angela Kang | 2013-02-24 | 11.01 | |
3 | Clear | Tricia Brock | Scott M. Gimple | 2013-03-03 | 11.30 | |
3 | Arrow on the Doorpost | David Boyd | Ryan C. Coleman | 2013-03-10 | 11.46 | |
3 | Prey | Stefan Schwartz | Glen Mazzara & Evan Reilly | 2013-03-17 | 10.84 | |
3 | This Sorrowful Life | Greg Nicotero | Scott M. Gimple | 2013-03-24 | 10.99 | |
3 | Welcome to the Tombs | Ernest Dickerson | Glen Mazzara | 2013-03-31 | 12.42 | |
4 | 30 Days Without an Accident | Greg Nicotero | Scott M. Gimple | 2013-10-13 | 16.11 | |
4 | Infected | Guy Ferland | Angela Kang | 2013-10-20 | 13.95 | |
4 | Isolation | Dan Sackheim | Robert Kirkman | 2013-10-27 | 12.92 | |
4 | Indifference | Tricia Brock | Matthew Negrete | 2013-11-03 | 13.31 | |
4 | Internment | David Boyd | Channing Powell | 2013-11-10 | 12.20 | |
4 | Live Bait | Michael Uppendahl | Nichole Beattie | 2013-11-17 | 12.00 | |
4 | Dead Weight | Jeremy Podeswa | Curtis Gwinn | 2013-11-24 | 11.29 | |
4 | Too Far Gone | Ernest Dickerson | Seth Hoffman | 2013-12-01 | 12.05 | |
4 | After | Greg Nicotero | Robert Kirkman | 2014-02-09 | 15.76 | |
4 | Inmates | Tricia Brock | Matthew Negrete & Channing Powell | 2014-02-16 | 13.34 | |
4 | Claimed | Seith Mann | Nichole Beattie & Seth Hoffman | 2014-02-23 | 13.12 | |
4 | Still | Julius Ramsay | Angela Kang | 2014-03-02 | 12.61 | |
4 | Alone | Ernest Dickerson | Curtis Gwinn | 2014-03-09 | 12.65 | |
4 | The Grove | Michael Satrazemis | Scott M. Gimple | 2014-03-16 | ||
4 | Us | David S. Goyer | 2014-03-23 | |||
4 | A | Michelle MacLaren | 2014-03-30 |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Walking Dead Viewership</title> | |
</head> | |
<style> | |
body, html{ | |
margin: 0; | |
width: 900px; | |
color: white; | |
background-color: black; | |
font-family: helvetica; | |
margin: auto; | |
} | |
.scatter-container{ | |
width: 50%; | |
float: left; | |
height: 400px; | |
} | |
.detail{ | |
width: 50%; | |
float: left; | |
height: 400px; | |
} | |
scatter{ | |
width: 100%; | |
height: 100%; | |
display: block; | |
z-index: 0; | |
overflow: hidden; | |
font-size: 10px; | |
} | |
scatter circle{ | |
opacity: 0.4; | |
cursor: pointer; | |
stroke-width: 2; | |
} | |
scatter circle:hover{ | |
stroke: white; | |
} | |
scatter text{ | |
fill: white; | |
stroke: none; | |
} | |
scatter .x-axis path, scatter .y-axis path{ | |
stroke: none; | |
fill: none; | |
} | |
scatter .x-axis line, scatter .y-axis line{ | |
stroke: rgba(255, 255, 255, 0.2); | |
} | |
</style> | |
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<body ng-app="myApp" ng-controller="MainCtrl"> | |
<h1>Walking Dead Viewership</h1> | |
<div class="scatter-container"> | |
<scatter | |
data="episodes" | |
accessor-x="d.air_date" | |
accessor-y="d.us_viewers" | |
selected-point="selectedEpisode" | |
color="color(d.season)"> | |
</scatter> | |
</div> | |
<div class="detail"> | |
<h2>Episode: {{selectedEpisode.title}}</h2> | |
<h3>season: {{selectedEpisode.season}}</h3> | |
<h3>us viewers: {{selectedEpisode.us_viewers | number}}</h3> | |
</div> | |
</body> | |
<script> | |
var app = angular.module('myApp', []); | |
app.controller('MainCtrl', function($scope, $window){ | |
$scope.color = d3.scale.category10(); | |
angular.element($window).on('resize', function(){ $scope.$apply(); }); | |
d3.csv('./episodes.csv', function(row){ | |
row.season = +row.season; // number | |
row.air_date = new Date(row.air_date); | |
row.us_viewers = +row.us_viewers * 1e6; // us viwers in millions | |
return row; | |
}, function(err, episodes){ | |
if(err){ throw err; } | |
$scope.$apply(function(){ | |
// remove the few episodes that haven't air yet at time of writing. | |
episodes = episodes.slice(0, -3); | |
$scope.episodes = episodes; | |
$scope.selectedEpisode = episodes[0]; | |
}); | |
}); | |
}); | |
app.directive('scatter', function(){ | |
function link(scope, el, attr){ | |
el = el[0]; | |
var w, h; | |
var svg = d3.select(el).append('svg'); | |
var xAxisG = svg.append('g').attr('class', 'x-axis'); | |
var yAxisG = svg.append('g').attr('class', 'y-axis'); | |
var points = svg.append('g').attr('class', 'points').selectAll('g.point'); | |
var x = d3.scale.linear(); | |
var y = d3.scale.linear(); | |
var yFormat = d3.format('.2s'); | |
var timeFormat = d3.time.format('%m-%y'); | |
var xFormat = function(d){ return timeFormat(new Date(d)) }; | |
var xAxis = d3.svg.axis().scale(x).orient('bottom').tickFormat(xFormat); | |
var yAxis = d3.svg.axis().scale(y).orient('left').tickFormat(yFormat); | |
var m = 50; | |
scope.$watch(function(){ | |
w = el.clientWidth; | |
h = el.clientHeight; | |
return w + h; | |
}, resize); | |
function resize(){ | |
svg.attr({width: w, height: h}); | |
x.range([m, w - m]); | |
y.range([h - m, m]); | |
xAxis.tickSize(-h + 2 * m); | |
yAxis.tickSize(-w + 2 * m); | |
xAxisG.attr('transform', 'translate(' + [0, y.range()[0] + 0.5] + ')'); | |
yAxisG.attr('transform', 'translate(' + [x.range()[0], 0] + ')'); | |
update(); | |
} | |
scope.$watch('data', update); | |
function update(){ | |
if(!scope.data){ return }; | |
var data = scope.data; | |
var x_extent = d3.extent(data, function(d){ return scope.accessorX({d:d}) }); | |
x.domain(x_extent); | |
var y_max = d3.max(data, function(d){ return scope.accessorY({d:d}) }); | |
y.domain([0, y_max]); | |
points = points.data(data); | |
points.exit().remove(); | |
var point = points.enter().append('g').attr('class', 'point'); | |
point.append('circle').attr('r', 5) | |
.style('fill', function(d){ return scope.color({d:d}); }) | |
.on('mouseover', function(d){ | |
scope.$apply(function(){ | |
scope.selectedPoint = d; | |
}); | |
}) | |
// update the position of all the points | |
points.attr('transform', function(d){ | |
return 'translate(' + [x(scope.accessorX({d:d})), y(scope.accessorY({d:d}))] + ')'; | |
}); | |
xAxisG.call(xAxis); | |
yAxisG.call(yAxis); | |
}; | |
} | |
return { | |
link: link, | |
restrict: 'E', | |
scope: { data: '=', accessorX: '&', accessorY: '&', color: '&', selectedPoint: '=' } | |
}; | |
}); | |
</script> | |
</html> |