Public
Edited
Jan 29, 2024
1 star
Insert cell
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Heatmap
const rects = svg
.selectAll("rects")
.data(data)
.enter()
.append("rect")
.attr("x", (d) => xScale(d.year))
.attr("y", margin.top)
.attr("width", xScale.bandwidth())
.attr("height", height - margin.top - margin.bottom)
.attr("fill", (d) => colorScale(d.avg));

// Legend
const legendRects = svg
.selectAll("legend-rects")
.data(legendData)
.enter()
.append("rect")
.attr("x", (d, i) => xLegendScale(i))
.attr("y", height - margin.bottom + 50)
.attr("width", xLegendScale.bandwidth())
.attr("height", 20)
.attr("fill", (d) => colorScale(d));

const legendLabels = svg
.selectAll("legend-labels")
.data(legendData)
.enter()
.append("text")
.attr("x", (d, i) => xLegendScale(i) + xLegendScale.bandwidth() / 2)
.attr("y", height - margin.bottom + 50 + 15)
.text((d) => d3.format(".1f")(d))
.style("fill", (d) => (Math.abs(d) >= 0.5 ? "#fff" : "#111"))
.attr("class", "legend-labels");

const unit = svg
.append("text")
.text("(°C)")
.attr("x", xLegendScale(legendData.length - 1) + 60)
.attr("y", height - margin.bottom + 50 + 15)
.attr("class", "legend-labels");

svg
.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.attr("class", "x-axis")
.call(xAxis);

return svg.node();
}
Insert cell
Insert cell
xAxis = d3
.axisBottom(xScale)
// .tickFormat((d) => formatXAxis(d))
.tickValues(xScale.domain().filter((d, i) => !(i % 10)))
// .tickSizeOuter(0)
Insert cell
Insert cell
legendData = d3.range(
d3.min(data, (d) => d.avg),
d3.max(data, (d) => d.avg),
0.2
)
Insert cell
xLegendScale = d3
.scaleBand()
.domain(legendData.map((d, i) => i))
// .range([margin.left + 250, width - margin.right - 250])
.range([width / 2 - 140, width / 2 + 140])
.paddingInner(0.1)
Insert cell
Insert cell
xScale = d3
.scaleBand()
.domain(data.map((d) => d.year))
.range([margin.left, width - margin.right])
.paddingInner(0.1)
Insert cell
margin = ({ top: 60, left: 50, right: 50, bottom: 120 })
Insert cell
Insert cell
colorScale = d3
.scaleSequential()
// .domain(d3.extent(data, (d) => d.avg).reverse())
// .domain([0.8, -0.8])
// .interpolator(d3.interpolateRdYlBu)
.domain([-0.8, 0.8])
.interpolator(d3.interpolatePuOr)
Insert cell
height = 480
Insert cell
Insert cell
data = raw_data
.filter((d) => d.Entity === "Global")
.map((d) => {
const obj = {};
obj.year = d.Year;
obj.avg = d["Global average temperature anomaly relative to 1961-1990"];
return obj;
})
Insert cell
raw_data = d3
.csvParse(
await FileAttachment("temperature-anomaly-data.csv").text(),
d3.autoType
)
Insert cell
Insert cell
html`<style>
.legend-labels {
font-family: arial;
font-size: 12px;
text-anchor: middle;
}

.x-axis .domain {
display: none;
}
</style>`
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