Published
Edited
Aug 23, 2020
1 fork
8 stars
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "-" + adj + " -"+ adj + " " + (width + adj*2) + " " + (height + adj*2))
.style("background", mode === "dark" ? "#2e2e2e" : "#fff");

const gradient_light = svg.append("linearGradient")
.attr("id","gradLight")
.attr("x1","0%")
.attr("y1","0%")
.attr("x2","0%")
.attr("y2","100%");

gradient_light.append("stop")
.attr("offset", "0%")
.attr("stop-color", "#6a915c");

gradient_light.append("stop")
.attr("offset", "60%")
.attr("stop-color", "#92ac7d");

gradient_light.append("stop")
.attr("offset", "95%")
.attr("stop-color", "#b8c8a0");
const gradient_dark = svg.append("linearGradient")
.attr("id","gradDark")
.attr("x1","0%")
.attr("y1","0%")
.attr("x2","0%")
.attr("y2","100%");

gradient_dark.append("stop")
.attr("offset", "0%")
.attr("stop-color", "#b8c8a0");

gradient_dark.append("stop")
.attr("offset", "60%")
.attr("stop-color", "#92ac7d");

gradient_dark.append("stop")
.attr("offset", "95%")
.attr("stop-color", "#6a915c");

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

svg.append("g")
.call(yAxis);
const group = svg.append("g")
.selectAll("g")
.data(data.series)
.join("g")
.attr("transform", d => `translate(0,${y(d.name) + 1})`);

group.append("path")
.attr("fill", mode==="dark"?"url(#gradDark)":"url(#gradLight)")
.attr("d", d => area(d.values));

group.append("path")
.attr("fill", "none")
.attr("stroke", mode==="dark"?"#f2e8d2":"#544208")
.attr("d", d => line(d.values));

return svg.node();
}
Insert cell
mode = Generators.observe(notify => {
const query = matchMedia("(prefers-color-scheme: dark)");
const changed = () => notify(query.matches ? "dark" : "light");
changed();
query.addListener(changed);
return () => query.removeListener(changed);
})
Insert cell
adj = 50
Insert cell
overlap = 5
Insert cell
width = 1000
Insert cell
height = 400
Insert cell
margin = ({top: 50, right: 20, bottom: 30, left: 40})
Insert cell
x = d3.scaleTime()
.domain(d3.extent(data.dates))
.range([margin.left, width - margin.right])
Insert cell
y = d3.scalePoint()
.domain(data.series.map(d => d.name))
.range([margin.top, height - margin.bottom])
Insert cell
z = d3.scaleLinear()
.domain([0, d3.max(data.series, d => d3.max(d.values))]).nice()
.range([0, -overlap * y.step()])
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.style("color", mode==="dark"?"#f2e8d2":"#544208")
.call(d3.axisBottom(x)
.ticks(width / 80)
.tickSizeOuter(0))
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.style("color", mode==="dark"?"#f2e8d2":"#544208")
.call(d3.axisLeft(y).tickSize(0).tickPadding(4))
.call(g => g.select(".domain").remove())
Insert cell
area = d3.area()
.curve(d3.curveBasis)
.defined(d => !isNaN(d))
.x((d, i) => x(data.dates[i]))
.y0(0)
.y1(d => z(d))
Insert cell
line = area.lineY1()
Insert cell
data = {
const data = d3.csvParse(await FileAttachment("ridgelineMood@2.csv").text(), d3.autoType);
const dates = Array.from(d3.group(data, d => +d.date).keys()).sort(d3.ascending);
return {
dates: dates.map(d => new Date(d)),
series: d3.groups(data, d => d.name).map(([name, values]) => {
const value = new Map(values.map(d => [+d.date, d.value]));
return {name, values: dates.map(d => value.get(d))};
})
};
}

Insert cell
d3 = require("d3@5", "d3-array@2")
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