|
<!DOCTYPE html> |
|
<svg width="960" height="500"></svg> |
|
<script src="https://d3js.org/d3.v4.min.js"></script> |
|
<script> |
|
|
|
var svg = d3.select("svg"), |
|
margin = {top: 20, right: 0, bottom: 20, left: 0}, |
|
width = +svg.attr("width") - margin.left - margin.right, |
|
height = +svg.attr("height") - margin.top - margin.bottom, |
|
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
var parseTime = d3.timeParse("%Y-%m-%d"); |
|
|
|
d3.json('positivityMonth.json', function(data) { |
|
|
|
var dates = data.dates; |
|
var counts = data.counts; |
|
|
|
var lowerY = -3, upperY = 3; |
|
|
|
var extent = d3.extent(data.counts); |
|
console.log("extent: ", extent); |
|
|
|
var normalized = []; |
|
var yRange = upperY - lowerY; |
|
var yShift = yRange / 2; |
|
var count; |
|
for (var i = 0; i < counts.length; i++) { |
|
count = ((counts[i] * yRange) / extent[1]) - yShift; |
|
normalized.push( { date: parseTime(dates[i]), count: count } ); |
|
} |
|
console.log("normalized: ", normalized[10]); |
|
console.log("date extent: ", d3.extent(data.dates)); |
|
|
|
var formatNumber = d3.format(".1f"); |
|
|
|
var xExtent = d3.extent(data.dates); |
|
console.log("xExtent: ", xExtent) |
|
console.log("type of xExtent[0]: ", typeof xExtent[0]) |
|
var x = d3.scaleTime() |
|
.domain([new Date(xExtent[0]), new Date(xExtent[1])]) |
|
.range([0, width]); |
|
|
|
var y = d3.scaleLinear() |
|
.domain([lowerY, upperY]) |
|
.range([height, 0]); |
|
|
|
var line = d3.line() |
|
.x(function(d) { console.log("x(d.date): ", typeof d.date); return x(d.date); }) |
|
.y(function(d) { return y(d.count); }); |
|
|
|
var xAxis = d3.axisBottom(x) |
|
.ticks(d3.timeDay.every(15)); |
|
|
|
var yAxis = d3.axisRight(y) |
|
.ticks(7) |
|
.tickSize(width) |
|
.tickFormat(function(d) { |
|
return d == 0 ? '' : Math.abs(+d).toString() + ' \u{03C3}'; |
|
}); |
|
|
|
function customXAxis(g) { |
|
g.call(xAxis); |
|
g.select(".domain").remove(); |
|
} |
|
|
|
function customYAxis(g) { |
|
var colors = { |
|
up: '#3F83D8', |
|
down: '#00D7CA' |
|
} |
|
g.call(yAxis); |
|
g.select(".domain").remove(); |
|
g.selectAll(".tick:not(:first-of-type) line") |
|
.attr("stroke", "lightgray"); |
|
g.selectAll(".tick text").attr("x", 4).attr("dy", function(d) { |
|
return d < 0 ? -4 : 10; |
|
}); |
|
g.selectAll(".tick:not(:first-of-type)") |
|
.append("rect") |
|
.attr("height", height / 6) |
|
.attr("width", width) |
|
.attr("fill", function(d) { return d >= 1 ? colors["down"] : colors["up"] } ) |
|
.attr("fill-opacity", function(d) { return 1 - (Math.abs(d) * .3); }); |
|
} |
|
|
|
g.append("g") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(customXAxis); |
|
|
|
g.append("g") |
|
.call(customYAxis); |
|
|
|
g.append("path") |
|
.datum(normalized) |
|
.attr("fill", "none") |
|
.attr("stroke", "steelblue") |
|
.attr("stroke-linejoin", "round") |
|
.attr("stroke-linecap", "round") |
|
.attr("stroke-width", 1.5) |
|
.attr("d", line); |
|
|
|
}) |
|
</script> |