xxxxxxxxxx
<meta charset="utf-8">
<style type="text/css">
body{
font-family:sans-serif;
background: #3c3a39;
}
div.container {
width:750px;
margin: 20px auto;
overflow:visible;
}
div.description {
padding: 0px 50px;
width:640px;
margin: 80px auto 20px auto;
border-bottom: 3px solid #ccc;
}
div.description p {
color: lightgreen;
line-height:38px;
font-size:33px;
font-family: serif;
}
text {
fill:white;
}
svg {
margin: 25px auto 20px auto;
}
path.domain {
fill:none;
}
text.year, text.month {
font-size:18px;
letter-spacing: 1px;
font-family: serif;
fill: lightgreen;
text-transform:uppercase;
}
.x-axis text {
font-size:12px;
fill: #888;
}
.y-axis text {
fill: #888;
font-size:12px;
}
circle {
fill: #d9d0ce;
}
div.subnote {
font-style: italic;
text-align:center;
font-size:13px;
margin-bottom:30px;
margin-top:-10px;
}
div.subnote, div.subnote a{
color: #999;
}
h2 {
text-transform: uppercase;
text-align:center;
font-size:16px;
color: #111;
}
.cssload-loading {
position: relative;
width: 40px;
height: 40px;
background: rgb(204, 204, 204);
display:block;
margin: auto;
animation: 1.15s cssload-spin infinite;
-o-animation: 1.15s cssload-spin infinite;
-ms-animation: 1.15s cssload-spin infinite;
-webkit-animation: 1.15s cssload-spin infinite;
-moz-animation: 1.15s cssload-spin infinite;
}
.cssload-loading::before, .cssload-loading::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
animation: 0.58s infinite alternate linear
}
.cssload-loading::before {
background: rgb(144, 238, 144);
-o-animation: 0.58s infinite alternate linear
}
.cssload-loading::before {
background: rgb(144, 238, 144);
-ms-animation: 0.58s infinite alternate linear
}
.cssload-loading::before {
background: rgb(144, 238, 144);
-webkit-animation: 0.58s infinite alternate linear
}
.cssload-loading::before {
background: rgb(144, 238, 144);
-moz-animation: 0.58s infinite alternate linear
}
.cssload-loading::before {
background: rgb(144, 238, 144);
animation-name: cssload-blur1;
-o-animation-name: cssload-blur1;
-ms-animation-name: cssload-blur1;
-webkit-animation-name: cssload-blur1;
-moz-animation-name: cssload-blur1;
}
.cssload-loading::after {
background: rgb(60,58,57);
animation-name: cssload-blur2;
-o-animation-name: cssload-blur2;
-ms-animation-name: cssload-blur2;
-webkit-animation-name: cssload-blur2;
-moz-animation-name: cssload-blur2;
}
@keyframes cssload-spin {
to {
transform: rotate(360deg);
}
}
@-o-keyframes cssload-spin {
to {
-o-transform: rotate(360deg);
}
}
@-ms-keyframes cssload-spin {
to {
-ms-transform: rotate(360deg);
}
}
@-webkit-keyframes cssload-spin {
to {
-webkit-transform: rotate(360deg);
}
}
@-moz-keyframes cssload-spin {
to {
-moz-transform: rotate(360deg);
}
}
@keyframes cssload-blur1 {
to {
transform: rotate(-30deg);
}
}
@-o-keyframes cssload-blur1 {
to {
-o-transform: rotate(-30deg);
}
}
@-ms-keyframes cssload-blur1 {
to {
-ms-transform: rotate(-30deg);
}
}
@-webkit-keyframes cssload-blur1 {
to {
-webkit-transform: rotate(-30deg);
}
}
@-moz-keyframes cssload-blur1 {
to {
-moz-transform: rotate(-30deg);
}
}
@keyframes cssload-blur2 {
to {
transform: rotate(-15deg);
}
}
@-o-keyframes cssload-blur2 {
to {
-o-transform: rotate(-15deg);
}
}
@-ms-keyframes cssload-blur2 {
to {
-ms-transform: rotate(-15deg);
}
}
@-webkit-keyframes cssload-blur2 {
to {
-webkit-transform: rotate(-15deg);
}
}
@-moz-keyframes cssload-blur2 {
to {
-moz-transform: rotate(-15deg);
}
}
#cssload-pgloading {
margin-top:100px;
}
</style>
<body>
<div class="description">
<p>Tunebot listening activity by day of week and time of day <i>since April 2014</i></p>
</div>
<div class="container">
<div id="cssload-pgloading">
<div class="cssload-loading"></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>
<script>
var weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var hours = ["12a","1a","2a","3a","4a","5a","6a","7a","8a","9a","10a","11a","12p","1p","2p","3p","4p","5p","6p","7p","8p","9p","10","11p"];
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]
var margin = {top: 50, right: 20, bottom: 50, left: 50};
var width = 750 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var maxRadius = 14;
drawPunchCard = function(svg, yearData) {
var arrayValues = yearData.map(function(week){
return d3.values(week.value);
});
var values = [].concat.apply([], arrayValues);
var rScale = d3.scale.linear()
.range([1,maxRadius])
.domain(d3.extent(values));
var yScale = d3.scale.ordinal()
.rangeRoundPoints([0,height])
.domain(weekday);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("right");
svg.append("g")
.attr("class", "y-axis")
.attr("transform", "translate(-"+margin.left+",0)")
.call(yAxis);
var xScale = d3.scale.ordinal()
.rangeRoundPoints([0,width])
.domain(hours);
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(height+(margin.bottom/2))
.orient("bottom");
svg.append("g")
.attr("class", "x-axis")
.call(xAxis);
yearData.forEach(function(week,wx){
var days = d3.entries(week.value);
svg.selectAll("circle-"+week.key)
.data(days)
.enter()
.append("circle")
.attr("cx", function(d) { return xScale(hours[+d.key]); })
.attr("cy", yScale(week.key))
.attr("r", function(d){ return rScale(d.value) });
});
};
clean = function(d) {
var timestamp = d.timestamp;
if( !isNaN(d.timestamp) ) {
timestamp *= 1000;
}
var date = moment(timestamp);
return {
timestamp: date.seconds(),
year: date.year(),
month: date.month(),
day: weekday[date.days()],
hour: date.hours()
}
};
ready = function(err, data) {
var nestedData = d3.nest()
.key(function(d){ return d.year + "/" + d.month; })
// .key(function(d){ return d.year; })
.key(function(d){ return d.day; })
.key(function(d){ return d.hour; })
.rollup(function(scrobbles) { return scrobbles.length })
.map(data);
d3.select("#cssload-pgloading").remove();
var container = d3.select("div.container");
var keys = d3.keys(nestedData);
for( var i=0; i< keys.length; i++) {
var yearMonth = keys[i];
var yearData = d3.entries(nestedData[yearMonth]);
var svg = container.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 splitYearMonth = yearMonth.split("/");
var prettyName = splitYearMonth.length>1 ? months[splitYearMonth[1]] + " " + splitYearMonth[0] : splitYearMonth[0];
svg.append("text")
.attr("class", "month")
.attr("transform", "translate(-"+(margin.left-10)+",-"+margin.top/1.5+")")
.text(prettyName);
drawPunchCard(svg,yearData);
}
};
d3.tsv("tunebotnbs_timestamp.tsv", clean, ready);
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js
https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js