Public
Edited
Apr 11, 2024
2 stars
Insert cell
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("width", width).attr("height", height);

const g = svg
.append("g")
// .attr('transform', `translate(${ width/2 },${ height/2 })`)
.style("font-size", 10)
.style("font-family", "sans-serif");

g.selectAll("box")
.data(global_data)
.enter()
.append("rect")
.attr("x", (d) => xScale(d.year))
.attr("y", (d) => margin.top + 30)
.attr("width", xScale.bandwidth())
.attr("height", (d) => height - margin.top - margin.bottom - 30)
.style("fill", (d) => color(d.avg));
// .style("stroke", (d) => color(d.avg));

g.append("text")
.text("Temperature (°C)")
.attr("x", margin.left)
.attr("y", margin.top + 20)
.attr("class", "label");

// Legend
const legendRects = svg
.selectAll("legend-rects")
.data(legendData)
.enter()
.append("rect")
.attr("x", (d, i) => xLegendScale(i))
.attr("y", height - margin.bottom + 30)
.attr("width", xLegendScale.bandwidth())
.attr("height", 23)
.attr("fill", (d) => color(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 + 30 + 16)
.text((d) => d3.format(".1f")(d))
.style("fill", (d) => (Math.abs(d) >= 0.5 ? "#fff" : "#111"))
.attr("class", "legend-labels");

return svg.node();
}
Insert cell
legendData = d3.range(
d3.min(global_data, (d) => d.avg),
d3.max(global_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])
.paddingInner(0.1)
Insert cell
Insert cell
yAxis = g => g
.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(yScale).tickSize(10).ticks(6))
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(
d3.axisBottom()
.scale(xScale)
.tickValues(xScale.domain().filter((d, i) => !(i % 20)))
)
Insert cell
Insert cell
Insert cell
Insert cell
color = d3.scaleLinear(
colorDomain,
// d3.quantize(d3.interpolateOranges, 10)
d3.quantize(d3.interpolateSpectral, 10).reverse()
)
Insert cell
colorDomain = {
const extent = d3.extent(global_data, d => d.avg )
const interpolated = d3.interpolate( ...extent )
return d3.quantize(interpolated, 10)
}
Insert cell
Insert cell
yScale = d3.scaleLinear()
.domain([lower_bound_ext[0], upper_bound_ext[1]])
.range([height - margin.bottom, margin.top])
Insert cell
xScale = d3.scaleBand()
.domain(global_data.map(d => d.year))
.range([margin.left, width - margin.right])
.padding(.2)
Insert cell
margin = ({ top: 30, right: 30, left: 60, bottom: 80 })
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
global_data = raw_data.filter(d => d.Entity === 'Global').map(d => {
const obj = {
year: d.Year,
lower_bound: d['Lower bound (95% confidence interval) of the annual temperature anomaly'],
upper_bound: d['Upper bound (95% confidence interval) of the annual temperature anomaly'],
avg: d['Global average temperature anomaly relative to 1961-1990']
}
return obj
})
Insert cell
raw_data = d3.csvParse(await FileAttachment("temperature-anomaly.csv").text(), d3.autoType)
Insert cell
html`
<style>

.tick {
font-size: 11px;
color: #8a8a8a;
}

.domain {
display: none;
}

.label {
font-size: 12px;
}

.legend-labels {
font-family: arial;
font-size: 12px;
text-anchor: middle;
}

</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