Published
Edited
Feb 13, 2021
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

svg
.append("g")
.selectAll("path")
.data(series)
.join("path")
.attr("fill", ({ key }) => color(key))
.attr("d", area);
// .append("title")
// .text(({ key }) => key);

svg.append("g").call(xAxis);

return svg.node();
}
Insert cell
Insert cell
styles = html`
<style>

.svg-tooltip {
font-family: sans-serif;
background: rgba(69,77,93,.9);
border-radius: .1rem;
color: #fff;
display: block;
font-size: 14px;
max-width: 320px;
padding: .2rem .4rem;
position: absolute;
text-overflow: ellipsis;
white-space: pre;
z-index: 300;
visibility: hidden;
}
</style>`
Insert cell
tooltip = {
chart;

const tooltip = d3
.select("body")
.append("div")
.attr("class", "svg-tooltip")
.style("position", "absolute")
.style("visibility", "hidden");

d3.selectAll("path")
.on("mouseover", function(d, i) {
// change the selection style
d3.select(this)
.attr('stroke-width', '2')
.attr("stroke", "black")
.style('fill', "yellow");

// This .map function returns key values, which can then be retrieved with keyValues[i] on hover.
const keyValues = series.map(function(d) {
return d.key.toString().split(',');
});
tooltip.style("visibility", "visible").text(keyValues[i]);
// keyValues[i]
})
.on("mousemove", function(d, i) {
tooltip
.style("top", d3.event.pageY - 10 + "px")
.style("left", d3.event.pageX + 10 + "px");
})
.on("mouseout", function(d, i) {
// change the selection style
d3.select(this)
.attr('stroke-width', '0')
.style("fill", ({ key }) => color(key));

tooltip.style("visibility", "hidden");
});
}
Insert cell
Insert cell
data = Object.assign(
d3.csvParse(
await FileAttachment("federal_outlays_function.csv").text(),
d3.autoType
)
)
Insert cell
Insert cell
Insert cell
data.columns.slice(1)
Insert cell
series = d3
.stack()
.keys(data.columns.slice(1))
.offset(d3.stackOffsetWiggle)
.order(d3.stackOrderInsideOut)(data)
Insert cell
series[0].data
Insert cell
area = d3
.area()
.x(d => xScale(d.data.date))
.y0(d => yScale(d[0]))
.y1(d => yScale(d[1]))
Insert cell
Insert cell
xScale = d3
.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([margin.left, width - margin.right])
Insert cell
yScale = d3.scaleLinear()
.domain([d3.min(series, d => d3.min(d, d => d[0])), d3.max(series, d => d3.max(d, d => d[1]))])
.range([height - margin.bottom, margin.top])
Insert cell
color = d3.scaleOrdinal()
.domain(data.columns.slice(1))
.range(d3.schemeCategory10)
Insert cell
Insert cell
xAxis = g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(
d3
.axisBottom(xScale)
.tickFormat(d3.format(".0f"))
.tickSizeOuter(0)
)
.call(g => g.select(".domain").remove())
Insert cell
Insert cell
margin = ({
top: 0,
right: 20,
bottom: 30,
left: 20
})
Insert cell
height = 500
Insert cell
Insert cell
d3 = require("d3@5")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more