function createViz() {
d3.csv("test.csv",type, function (error, data) {
if (error) throw error;
dataViz(data)
});
}
function dataViz(data) {
//setup tooltip div & nav rect
var tooltip = d3.select("#tooltip")
.style("opacity", 0);
// Parse the date / time
var formatDate = d3.time.format("%d-%b"),
formatMth = d3.time.format("%m-%d"),
formatYear = d3.time.format("%Y");
var bisect = d3.bisector(function(d) { return d.xPos; }).right;
data.forEach(function(d,i) {
d.xPos = formatMth(d.date);
});
var margin = {top: 5, right: 10, bottom: 5, left: 10},
width = 960 - margin.left - margin.right,
height = 100 - margin.top - margin.bottom;
//this works as an x domain with range bands
var x = d3.scale.ordinal().rangeRoundBands([0, width], 0.2);
var y = d3.scale.linear().range([0,height]);
var dataPerYear = d3.nest()
.key(function(d) { return formatYear(d.date);})
.entries(data);
//x.domain(),needs to have "02-29" added manually
//have tried this but it just gets added to the end
//x.domain(data.map(function(d) { return d.xPos, "02-29"; }));
// x.domain(data.map(function(d) { return d.xPos; }));
var leapYearDays = [];// will be populated with all dates
var currentDate = new Date(2016, 0, 1);// the date we'll be incrementing
var safety = 0;// helps prevent infinite looping during development
while(safety < 400 && currentDate.getFullYear() == 2016) {
leapYearDays.push(formatMth(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
safety++;
}
x.domain(leapYearDays.map(function(d) { return d; }));
y.domain([0, d3.max(data, function(d) { return d.rain; })]);
var svg = d3.select("#chart").selectAll("svg")
.data(dataPerYear)
.enter().append("svg")
.attr("class", "charts")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("text")
.attr("class", "year")
.attr("transform", "rotate(-90)")
.attr("y", 100)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text(function(d) { return d.key; });
svg.selectAll(".bar")
.data(function(d) {return d.values;})
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(formatMth(d.date)); })
.style("fill", function(d) { return d.date.getMonth() == 1 && d.date.getDate() == 29 ? "red" : null})
.attr("y", 0)
.attr("width", x.rangeBand())
.attr("height", 0)
.transition()
.duration(1000)
.ease("quad")
.attr("height", function(d) { return y(d.rain); });
var focus = svg.append("g");
focus.style("display", "none");
// append the rect at the intersection
focus.append("rect")
.attr("class", function(d) { return "y"+d.key; })
.style("opacity", 0.5)
.style("fill", "none")
.attr("width", x.rangeBand())
.attr("height", height);
// append the rectangle to capture mouse
svg.append("rect")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("id", function(d,i) { return i; })
.attr("chartID", function(d,i) { return i; })
.attr("yearID", function(d) { return d.key; })
.style("fill", "none")
.style("pointer-events", "all")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("mousemove", mousemove);
function mousemove() {
//use this for inverting ordinal scale https://stackoverflow.com/questions/20758373/inversion-with-ordinal-scale (sepans in the comments)
var chartID = d3.select(this);
var keyID = chartID.attr("chartID");
var yearID = chartID.attr("yearID");
var id = document.getElementById(keyID);
//for using getBoundingClientRect() http://help.dottoro.com/ljvmcrrn.php
var yPosPerChart = parseInt(id.getBoundingClientRect().top+20);
var domain = x.domain(),
xpos = d3.mouse(this)[0],
range = x.range();
var x0 = domain[d3.bisect(range, xpos) - 1],
i = bisect(dataPerYear[keyID].values, x0),
d0 = dataPerYear[keyID].values[i - 1],
d1 = dataPerYear[keyID].values[i];
d = x0 - d0.date > d1.date - x0 ? d1 : d0;
tooltip.transition()
.duration(50)
.style("opacity", .9);
tooltip.html(""+formatDate(d.date)+","+yearID+"
rainfall: "+d.rain+"mm")
.style("left", (d3.event.pageX+20) + "px")
.style("top", (d3.event.pageY+20) + "px");
//detect yPos
//.style("top", yPosPerChart + "px");
focus.style("display", null);
focus.select("rect.y"+yearID)
.attr("transform",
"translate(" + x(formatMth(d.date)) + ",0)")
.style("fill", "pink");
}
function mouseover() {
tooltip.style("opacity",.9);
}
function mouseout(){
tooltip.style("opacity", 0);
focus.select("rect")
.style("fill", "none");
focus.style("display", "none");
}
}
function type(d) {
//var format = d3.time.format("%d-%b-%Y");
var format = d3.time.format("%d-%b-%y");
d.rain = +d.rain;
d.date = format.parse(d.date);
return d;
}