|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
body { |
|
font: 10px sans-serif; |
|
} |
|
|
|
.chart { |
|
background: #fff; |
|
} |
|
|
|
p { |
|
font: 12px helvetica; |
|
} |
|
|
|
|
|
.axis path, |
|
.axis line { |
|
fill: none; |
|
stroke: grey; |
|
stroke-width: 2px; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.grid .tick { |
|
stroke: grey; |
|
stroke-opacity: 0.2; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.tooltip { background-color:rgba(68,136,187,0.5);; |
|
margin: 10px; |
|
height: 50px; |
|
width: 150px; |
|
padding-left: 10px; |
|
padding-top: 10px; |
|
-webkit-border-radius:10px; |
|
-moz-border-radius:10px; |
|
border-radius:10px; |
|
} |
|
|
|
</style> |
|
<body> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<!-- <script type="text/javascript" src="tooltip.js"></script> --> |
|
<script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script> |
|
<div class="chart"> |
|
</div> |
|
|
|
<script> |
|
// "blue" |
|
colorrange = ["#045A8D", "#2B8CBE", "#74A9CF", "#A6BDDB", "#D0D1E6", "#F1EEF6"]; |
|
// "pink" |
|
//colorrange = ["#980043", "#DD1C77", "#DF65B0", "#C994C7", "#D4B9DA", "#F1EEF6"]; |
|
// "orange" |
|
//colorrange = ["#B30000", "#E34A33", "#FC8D59", "#FDBB84", "#FDD49E", "#FEF0D9"]; |
|
|
|
|
|
chart("data.csv", colorrange); |
|
|
|
var datearray = []; |
|
var colorrange = []; |
|
|
|
|
|
function chart(csvpath, colorrange) { |
|
|
|
strokecolor = colorrange[0]; |
|
|
|
var format = d3.time.format("%Y-%m-%d"); |
|
|
|
var margin = {top: 20, right: 40, bottom: 40, left: 30}; |
|
var width = document.body.clientWidth - margin.left - margin.right; |
|
var height = 400 - margin.top - margin.bottom; |
|
|
|
// function for the x grid lines |
|
function make_x_axis() { |
|
return d3.svg.axis() |
|
.scale(x) |
|
.orient("bottom") |
|
.ticks(d3.time.months) |
|
} |
|
|
|
|
|
var tooltip = d3.select("body") |
|
.append("div") |
|
.attr("class", "remove") |
|
.style("position", "absolute") |
|
.style("z-index", "20") |
|
.style("visibility", "hidden") |
|
.style("top", "320px") |
|
.style("left", "45px"); |
|
|
|
var x = d3.time.scale() |
|
.range([0, width]); |
|
|
|
var y = d3.scale.linear() |
|
.range([height - 10, 0]); |
|
|
|
var z = d3.scale.ordinal() |
|
.range(colorrange); |
|
|
|
var xAxis = make_x_axis(); |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(y); |
|
|
|
var stack = d3.layout.stack() |
|
.offset("silhouette") |
|
.values(function(d) { return d.values; }) |
|
.x(function(d) { return d.date; }) |
|
.y(function(d) { return d.value; }); |
|
|
|
var nest = d3.nest() |
|
.key(function(d) { return d.key; }); |
|
|
|
var area = d3.svg.area() |
|
.interpolate("cardinal") |
|
.x(function(d) { return x(d.date); }) |
|
.y0(function(d) { return y(d.y0); }) |
|
.y1(function(d) { return y(d.y0 + d.y); }); |
|
|
|
var svg = d3.select(".chart").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 graph = d3.csv(csvpath, function(data) { |
|
data.forEach(function(d) { |
|
d.date = format.parse(d.date); |
|
d.value = +d.value; |
|
}); |
|
|
|
var layers = stack(nest.entries(data)); |
|
|
|
var xdom = d3.extent(data, function(d) { return d.date; }); |
|
x.domain(xdom); |
|
y.domain([0, d3.max(data, function(d) { return d.y0 + d.y; })]); |
|
|
|
svg.selectAll(".layer") |
|
.data(layers) |
|
.enter().append("path") |
|
.attr("class", "layer") |
|
.attr("d", function(d) { return area(d.values); }) |
|
.style("fill", function(d, i) { return z(i); }); |
|
|
|
// Draw the x Grid lines |
|
svg.append("g") |
|
.attr("class", "grid") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(make_x_axis() |
|
.tickSize(-height, 0, 0) |
|
.tickFormat("") |
|
); |
|
|
|
svg.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(xAxis) |
|
.selectAll("text") // rotate ticks labels |
|
.attr("y", 0) |
|
.attr("x", 9) |
|
.attr("dy", ".35em") |
|
.attr("transform", "rotate(40)") |
|
.style("text-anchor", "start"); |
|
|
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.attr("transform", "translate(" + width + ", 0)") |
|
.call(yAxis.orient("right")); |
|
|
|
svg.append("g") |
|
.attr("class", "y axis") |
|
.call(yAxis.orient("left")); |
|
|
|
// the cursor for the tooltip |
|
var axisExtentLine = svg.append("line") |
|
.attr({"class": "extent", |
|
"stroke-width": 5, |
|
"stroke-opacity": 0.8, |
|
"stroke": "red", |
|
"pointer-events": "none" |
|
}); |
|
|
|
// the cursor in the stream under the mouse |
|
var cursorExtentLine = svg.append("line") |
|
.attr({"class": "extent", |
|
"stroke-width": 3, |
|
"stroke-opacity": 0.8, |
|
"stroke": "white", |
|
"pointer-events": "none" |
|
}); |
|
|
|
svg.selectAll(".layer") |
|
.attr("opacity", 1) |
|
.on("mouseover", function(d, i) { |
|
svg.selectAll(".layer").transition() |
|
.duration(250) |
|
.attr("opacity", function(d, j) { |
|
return j != i ? 0.6 : 1; |
|
}) |
|
.attr("stroke", function(d, j) { |
|
return j != i ? "none" : "black"; |
|
}) |
|
}) |
|
/* .call(d3.helper.tooltip( |
|
function(d, i){ |
|
console.log(d); |
|
console.log(i); |
|
console.log(d.values); |
|
return "<b>"+d + "</b><br/>pop: "+d; |
|
} |
|
)) */ |
|
.on("mousemove", function(d, i) { |
|
mouse = d3.mouse(this); |
|
// get the date at mouse position |
|
var dateATx = x.invert(mouse[0]); |
|
// make it the fisrt of the month |
|
dateATx = new Date(dateATx.getFullYear(), dateATx.getMonth(), 1); |
|
// get the entry in d.values that matches the first of the month under the mouse |
|
var entry = _.find(d.values, function(o) {return o.date.getTime() == dateATx.getTime();}); |
|
|
|
pro = entry.value || 0; |
|
var posY = entry.y0; |
|
var posX = x(entry.date); |
|
|
|
axisExtentLine.attr({x1: 0, y1: y(pro), |
|
x2: 0, y2: height -10 }); |
|
cursorExtentLine.attr({x1: posX, y1: y(pro) - (height - y(posY) - 10), |
|
x2: posX, y2: height - (height - y(posY)) }); |
|
|
|
d3.select(this) |
|
.classed("hover", true) |
|
.attr("stroke", strokecolor) |
|
.attr("stroke-width", "1px"), |
|
tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ) |
|
.style("visibility", "visible"); |
|
|
|
}) |
|
// .on("mouseout", fade(1)) |
|
|
|
.on("mouseout", function(d, i) { |
|
svg.selectAll(".layer") |
|
.transition() |
|
.duration(250) |
|
.attr("opacity", "1"); |
|
d3.select(this) |
|
.classed("hover", false) |
|
.attr("stroke-width", "0px"); |
|
tooltip.html( "<p>" + d.key + "<br>" + pro + "</p>" ) |
|
.style("visibility", "hidden"); |
|
}) |
|
|
|
var vertical = d3.select(".chart") |
|
.append("div") |
|
.attr("class", "remove") |
|
.style("position", "absolute") |
|
.style("z-index", "19") |
|
.style("width", "1px") |
|
.style("height", "340px") |
|
.style("top", "20px") |
|
.style("bottom", "30px") |
|
.style("left", "0px") |
|
.style("background", "#f00"); |
|
|
|
d3.select(".chart") |
|
.on("mousemove", function(){ |
|
mousex = d3.mouse(this); |
|
mousex = mousex[0] + 5; |
|
vertical.style("left", mousex + "px" )}) |
|
.on("mouseover", function(){ |
|
mousex = d3.mouse(this); |
|
mousex = mousex[0] + 5; |
|
vertical.style("left", mousex + "px")}); |
|
}); |
|
} |
|
|
|
function fade(opacity) { |
|
return function(g, i) { |
|
streamgraph.layers() |
|
.filter(function(h, j) { |
|
return j != i; |
|
}) |
|
.transition(1000) |
|
.style("opacity", opacity); |
|
} |
|
} |
|
|
|
</script> |