|
//Speed & animation-control variables |
|
var maprate = 4760/12, |
|
pause=0, |
|
timepause=0, |
|
start = 0, |
|
interval, |
|
loop, |
|
dateiter; |
|
|
|
//Data parameter variables |
|
var minyr, |
|
maxyr, |
|
dates, |
|
years; |
|
|
|
//Selection variables |
|
var slider, |
|
handle, |
|
brush, |
|
timer, |
|
timeaxis, |
|
timescale = d3.time.scale(), |
|
datemark; |
|
|
|
var timepad = 100; //bottom padding for slider |
|
|
|
var width = Math.max(960, window.innerWidth), |
|
height = Math.max(700, window.innerHeight); |
|
|
|
// load data |
|
d3.csv("time.csv", |
|
type, |
|
function(error, data) { |
|
|
|
dates = d3.set(data.map(function(d) {return d.Date;})).values().map(function(z) {return new Date(z);}); |
|
|
|
years = d3.set(data.map(function(d) {return +d.Date.getFullYear();})).values().map(function(z) {return +z;}); |
|
|
|
minyr = d3.min(years); |
|
maxyr = d3.max(years); |
|
|
|
timescale |
|
.rangeRound([0,width - 40]) |
|
.clamp(true) |
|
; |
|
|
|
timeaxis = d3.svg.axis() |
|
.scale(timescale) |
|
.orient("bottom") |
|
.tickSize(0) |
|
.tickPadding(12) |
|
.ticks(0) |
|
; |
|
|
|
sliderbox = d3.select("#sliderbox") |
|
.attr("width",1800); |
|
|
|
timer = sliderbox.append("g"); |
|
|
|
timescale .domain([new Date(minyr,0,1),new Date(maxyr,12,31)]); |
|
|
|
timer |
|
.attr("class", "x axis") |
|
.attr("transform","translate(" + 20 + "," + Math.floor((height - (timepad/2))) + ")") |
|
.call(timeaxis) |
|
.select(".domain") |
|
|
|
brush = d3.svg.brush() |
|
.x(timescale) |
|
.extent([0,0]) |
|
.on("brush",function() { //Now separate into mousedown -> clearInterval, drag -> animate, mouseup -> setInterval components |
|
var mouseval = timescale.invert(d3.mouse(this)[0]); |
|
var val = new Date(mouseval.getFullYear(),12); |
|
var strval = val.toISOString(); |
|
dateiter = dates.map(function(d) {return d.toISOString();}).indexOf(strval); |
|
brush.extent([val,val]); |
|
//handle.attr("cx",timescale(val)); |
|
handle.attr("transform","translate(" + timescale(val) + ",0)") |
|
clearInterval(interval); |
|
update(data,val); |
|
interval = setInterval(loop,maprate); |
|
}) |
|
; |
|
|
|
slider = timer |
|
.append("g") |
|
.attr("class","slider") |
|
.call(brush) |
|
; |
|
slider.selectAll(".extent,.resize") |
|
.remove(); |
|
|
|
dateiter = 0; |
|
|
|
handle = slider .append("g") |
|
.attr("class","handle preload") |
|
.attr("transform","translate(" + timescale(dates[0]) + ",0)"); |
|
|
|
handle.append("line") |
|
.attr("class","datemark outer preload"); |
|
|
|
handle.append("line") |
|
.attr("class","datemark inner preload"); |
|
|
|
handle.append("text") |
|
.attr("class","datemark label") |
|
.attr("y",-12) |
|
.attr("x",0) |
|
.attr("text-anchor","middle"); |
|
|
|
d3.selectAll(".datemark.preload") // size of brush dragger |
|
.attr("x1",0) |
|
.attr("x2",0) |
|
.attr("y1",-5) |
|
.attr("y2",5); |
|
|
|
dateiter = 0; // date incrementer - start |
|
|
|
loop = function(){ |
|
clearInterval(interval); |
|
if ((timepause == 0 && pause == 0) || start == 0) { |
|
update(data,dates[dateiter]); |
|
if (dateiter < dates.length - 1) {++dateiter;} |
|
else { |
|
dateiter = 0; |
|
timepause=1; |
|
setTimeout(function(){timepause = 0;},3000); |
|
} |
|
} |
|
start = 1; |
|
interval = setInterval(loop, maprate); |
|
} |
|
|
|
interval = setInterval(loop, maprate); |
|
|
|
}); //end data callback |
|
|
|
|
|
|
|
function update(data,date) { |
|
var yr = date.getFullYear(); // spits out the years for slider |
|
|
|
var usedat = data.filter(yrfilter(yr)); |
|
|
|
var curr = [timescale(date)]; |
|
|
|
handle |
|
.transition(50) |
|
.attr("transform",function(d) {return "translate(" + Math.floor(curr) + ",0)"}); |
|
|
|
timer.selectAll(".datemark,.handle") // point that moves on timer |
|
.classed('preload',0); |
|
|
|
timer.select(".datemark.label") |
|
.text(d3.time.format("%Y")(date)); |
|
|
|
timer.select(".datemark.labelbox") |
|
.attr("height", 50) |
|
.attr("width", 50) |
|
.attr("x", 5) |
|
.attr("y",-12) |
|
.style("fill-opacity",0); |
|
|
|
var datapoints = d3.select("#points").selectAll("circle").data(data) |
|
.enter() |
|
.append("circle") |
|
.attr("class", function(d){return "dot " +d.Year}); |
|
|
|
var circles = d3.selectAll(".dot") |
|
.classed({'preload': false, 'loaded': true}) |
|
.data(usedat, function(d) { return d ? d.Radius : this.id; }, function(d) { return d ? d.x : this.id; }, function(d) { return d ? d.y : this.id; }); |
|
|
|
circles |
|
.transition() |
|
.duration(475) |
|
.attr("r", function(d){return d.Radius}) |
|
.attr("cx", function(d){return d.x}) |
|
.attr("cy", function(d){return d.y}) |
|
.style("fill", "#ff0000") |
|
.style("opacity", 1) |
|
.transition() |
|
.duration(300) |
|
.attr("r", function(d){return d.Radius}) |
|
.attr("cx", function(d){return d.x}) |
|
.attr("cy", function(d){return d.y}) |
|
.style("fill", "#ff0000") |
|
.style("opacity", 0.7) |
|
.transition() |
|
.duration(250) |
|
.attr("r", function(d){return d.Radius}) |
|
.attr("cx", function(d){return d.x}) |
|
.attr("cy", function(d){return d.y}) |
|
.style("fill", "#ff0000") |
|
.style("opacity", 0.5) |
|
.transition() |
|
.duration(150) |
|
.attr("r", function(d){return d.Radius}) |
|
.attr("cx", function(d){return d.x}) |
|
.attr("cy", function(d){return d.y}) |
|
.style("fill", "#ff0000") |
|
.style("opacity", 0.2) |
|
.remove(); |
|
|
|
|
|
} //end update |
|
|
|
//Filter by year. |
|
function yrfilter(year) { |
|
return function(element) { |
|
return element.Year == year; |
|
} |
|
} |
|
|
|
function type(d) { |
|
d.Year = +d.Year; |
|
d.Date = new Date(d.Year,12); |
|
return d; |
|
} |