Published
Edited
Oct 18, 2019
1 star
Insert cell
md`# Stacked Bar Chart - Monthly series`
Insert cell
chart = {
// Initialize svg
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
// .style("background-color", "lightgrey");

// Append the grid lines on X axis
// svg.append("g")
// .attr("class", "grid")
// .attr("transform", `translate(${x.bandwidth()/2}, ${height - margin.bottom})`)
// .call(make_x_gridlines()
// .tickSize(-height)
// .tickFormat("")
// )

// Append the bars
svg.append("g")
.selectAll("g")
.data(series)
.enter().append("g")
.attr("fill", d => color(d.key))
.attr("data-legend", d => d.key)
// .attr("class", d => color(d.key))
.selectAll("rect")
.data(d => d)
.enter().append("rect")
// .attr("class", d => color(d.key))
.attr("width", x.bandwidth)
.attr("x", d => x(new Date(d.data.fordate)))
.attr("y", d => y(d[1]))
.attr("height", d => y(d[0]) - y(d[1]))

// Append the X-axis
svg.append("g")
.call(xAxis);

// Append the Y-axis
svg.append("g")
.call(yAxis)
// Append X-axis label
// svg.append("text")
// .attr("class", "x-axis-label")
// .attr("transform", `translate(${width/2}, ${height - margin.top})`)
// .style("text-anchor", "middle")
// .text("Hour of the day")
// Append the legend
// svg.append("g")
// .attr("class", "legend_auto")
// .style('font-size', 12)
// .style('font-family', 'sans-serif')
// .attr("transform", "translate(650, 10)")
// .call(legend_auto)
const legend = svg.selectAll('.legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'legend')
.attr('transform', (d, i) => {
let legendHeight = legendRectSize + legendSpacing;
let x = width - margin.right;
let y = i * legendHeight + margin.top;
return `translate(${x}, ${y})`;
});

legend.append('rect')
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.style('fill', color)
.style('stroke', color);

legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize)
.text(d => d);

// Return generated svg
return svg.node();
}
Insert cell
html`
<style>
.grid line {
stroke: lightgrey;
stroke-opacity: .4;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
.x-axis-label {
font-weight: bold;
}
g.green-bar {
fill: #007f00;
}
g.blue-bar {
fill: royalblue;
}
g.striped-bar {
mask: url(#mask-stripe);
}
</style>
`
Insert cell
legendSpacing = 5
Insert cell
legendRectSize = 10
Insert cell
legend_auto = d3Legend
.legendColor()
.scale(color)
.labels(color.domain())
Insert cell
// color = d3.scaleOrdinal(d3.schemeCategory10);
color = d3.scaleOrdinal()
.domain(series.map(d => d.key))
// .range(["green-bar", "blue-bar", "striped-bar green-bar", "striped-bar blue-bar"])
.range(["#7f0000", "#007f00", "#00007f", "#7f7f7f"])
.unknown("#ccc");
Insert cell
// Function to produce gridlines in y-axis
make_x_gridlines = () => d3.axisBottom(x);
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(null, "s"))
// .call(g => g.selectAll(".domain").remove())
Insert cell
y = d3.scaleLinear()
.domain([d3.min(series, d => d3.min(d, d => d[0])), d3.max(series, d => d3.max(d, d => d[1]))])
.rangeRound([height - margin.bottom, margin.top])
Insert cell
// xAxis = d3.axisBottom(x).tickSize(0).tickFormat(d3.timeFormat("%Y"));
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom + 10})`)
.call(d3.axisBottom(x)
.tickSize(0)
// .ticks(d3.timeMonth.every(3))
// .tickFormat(d => d <= d3.timeYear(d) ? (d.getFullYear()) : null))
.tickFormat(d => d <= d3.timeYear(d) ? d3.timeFormat("%m-%Y")(d) : null))
.call(g => g.selectAll(".domain").remove())
// .selectAll("text")
// .attr("y", 0)
// .attr("x", 9)
// .attr("dy", ".35em")
// .attr("transform", "rotate(-45)")
// .style("text-anchor", "end");

Insert cell
x = d3.scaleBand()
.domain(data.map(d => new Date(d.fordate)))
.rangeRound([margin.left, width - margin.right])
.padding(0.2)
Insert cell
width = height * 16 / 9
Insert cell
height = 700
Insert cell
margin = ({top: 10, right: 100, bottom: 50, left: 40})
Insert cell
series = d3.stack().keys(data.columns.slice(9,13)).offset(d3.stackOffsetDiverging)(data)
Insert cell
data = (await
d3.csv("https://gist.githubusercontent.com/sashtur/ea60b1edca2f6d32ce429edbed09021f/raw/73474a64e5882dffc50a2a505b94dcf464205801/stacked%2520bar%2520graph", d3.autoType)
)
Insert cell
d3 = require("d3@5")
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
d3Legend = require('d3-svg-legend')
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