Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis--x path,
.axis--y path{
display: none;
}
.axis-title {
fill: black;
}
.contracts path {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
.voronoi path {
fill: none;
stroke: rgba(0,0,0,0.1);
pointer-events: all;
}
.focus {
text-anchor: middle;
}
.tooltip {
max-width: 55px;
width: 100%;
font-size: 12px;
}
.tooltip-top {
background: white;
border: 0.5px solid #F2F2F2;
border-top-left-radius: 1em;
border-top-right-radius: 1em;
padding: 0.4em 0.5em 0.1em;
width: 100%;
}
.tooltip-bottom {
background: #F2F2F2;
border: 0.5px solid #F2F2F2;
border-bottom-left-radius: 1em;
border-bottom-right-radius: 1em;
padding: 0.1em 0.5em 0.4em;
width: 100%;
}
.tooltip-arrow {
margin: 0 auto;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid #F2F2F2;
}
.focus text tspan:first-child{
fill: gray;
}
.focus text tspan:last-child{
fill: black;
}
</style>
</head>
<body>
<script src="data.js"></script>
<script>
// Feel free to change or delete any of the code you see in this editor!
var g3 = {
opts: {},
dimensions: {
width: 0,
height: 0
},
data: [],
bindTo: "body"
};
g3.timeseries = function(opts) {
return new Chart(opts);
}
var Chart = function(opts) {
self = Object.assign(this, g3);
initialize(opts);
function initialize(opts) {
self.opts = opts;
self.bindTo = self.opts.bindTo || self.bindTo;
self.d3DOM = d3.select(self.bindTo);
self.dimensions.width = +self.d3DOM.style("width").slice(0, -2);
self.dimensions.height = +self.d3DOM.style("height").slice(0, -2);
self.d3DOM.on("resize", resize);
renderAxis();
}
function renderAxis() {
var xColumn = self.opts.axis.x.column,
yColumn = self.opts.axis.y.column,
xFormat = self.opts.axis.x.format,
yFormat = self.opts.axis.y.format,
margin = self.margin = self.opts.margin,
width = self.dimensions.width - margin.left - margin.right,
height = self.dimensions.height - margin.top - margin.bottom;
var data = self.opts.data.map(function(d) {
d[xColumn] = xFormat(d[xColumn]);
d[yColumn] = yFormat(d[yColumn]);
return d;
});
var x = d3.scaleTime()
.range([0, width])
.domain(d3.extent(data, function(d) { return d[xColumn]; }));
var y = d3.scaleLinear()
.range([height, 0])
.domain(d3.extent(data, function(d) { return d[yColumn]; }));
var line = d3.line()
.x(function(d) { return x(d[xColumn]); })
.y(function(d) { return y(d[yColumn]); });
var voronoi = d3.voronoi()
.x(function(d) { return x(d[xColumn]); })
.y(function(d) { return y(d[yColumn]); })
.extent([[-margin.left, -margin.top], [width + margin.right, height + margin.bottom]]);
self.x = x;
self.y = y;
self.xColumn = xColumn;
self.yColumn = yColumn;
self.line = line;
self.voronoi = voronoi;
self.data = data;
updateDOM();
}
function updateDOM() {
var d3DOM = self.d3DOM,
margin = self.margin,
width = self.dimensions.width - margin.left - margin.right,
height = self.dimensions.height - margin.top - margin.bottom;
data = self.data,
line = self.line,
voronoi = self.voronoi,
x = self.x,
y = self.y;
var svg = d3DOM.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 + ")");
svg.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
svg.append("g")
.attr("class", "axis axis--y")
.call(d3.axisRight(y))
.append("text")
.attr("class", "axis-title")
.attr("transform", "rotate(-90)")
.attr("y", -16)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Dollars obligated ($)");
svg.append("g")
.attr("class", "contracts")
.append("path")
.datum(data)
.attr("d", line);
var voronoiGroup = svg.append("g")
.attr("class", "voronoi");
voronoiGroup.selectAll("path")
.data(voronoi.polygons(data))
.enter().append("path")
.attr("d", function(d) { return d ? "M" + d.join("L") + "Z" : null; })
.on("mouseover", mouseover)
.on("mouseout", mouseout);
var focus = svg.append("g")
.attr("transform", "translate(-100,-100)")
.attr("class", "focus");
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("display", "none");
self.focus = focus;
self.tooltip = tooltip;
function mouseover(d) {
focus = self.focus;
tooltip = self.tooltip;
focus.attr("transform", "translate(" + self.x(d.data[self.xColumn]) + "," + self.y(d.data[self.yColumn]) + ")");
tooltip.selectAll("div").remove()
tooltip.append("div")
.attr("class", "tooltip-top")
.text(function() {
return d3.timeFormat("%x")(d.data[self.xColumn])
})
tooltip.append("div")
.attr("class", "tooltip-bottom")
.text("$"+d.data[self.yColumn])
tooltip.style("display", "block")
.style("top", (self.y(d.data[self.yColumn])-40) + "px")
.style("left", (self.x(d.data[self.xColumn])+10) + "px")
tooltip.append("div")
.attr("class", "tooltip-arrow")
}
function mouseout(d) {
self.tooltip.style("display","none")
self.focus.attr("transform", "translate(-100,-100)");
}
}
function resize() {
initialize(this.opts);
}
}
g3.timeseries({
data: data,
margin: {top: 20, right: 20, bottom: 30, left: 50},
axis: {
x: {
column: "date",
format: function(d) {
return d3.timeParse("%d-%b-%y")(d);
}
},
y: {
column: "close",
format: function(d) {
return +d;
}
}
}
});
</script>
</body>
https://d3js.org/d3.v4.min.js