Public
Edited
Oct 24, 2024
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
chart = () => {
const svg = d3.create("svg")
.attr("width", chartwidth + margin.left + margin.right)
.attr("height", chartheight + margin.top + margin.bottom);

svg.append("style").html(css);

const g = svg.append("g")
.attr("transform", `translate(${[margin.left, margin.top]})`);

g.append("g")
.attr("class", "axis y-axis")
.call(
d3.axisLeft(y)
.tickFormat(d => `${d > 0 ? "+" : ""}${+d.toFixed(1)}°C`)
.tickSize(8)
.tickValues(d3.range(-1, 3))
)
g.append("g")
.attr("class", "axis x-axis")
.attr("transform", `translate(0, ${chartheight})`)
.call(
d3.axisBottom(x)
.tickFormat(d => d)
.tickSize(8)
.tickValues(d3.range(1850, 2050, 50))
)

g.append("line")
.attr("class", "baseline")
.attr("transform", `translate(0, ${y(0)})`)
.attr("x2", chartwidth);

g.append("line")
.attr("class", "baseline")
.attr("y1", y(2))
.attr("y2", y(-1));

g.append("path")
.datum(temperature_sources)
.attr("fill", colors.aerBg)
.attr("d", areaAer);

g.append("path")
.datum(temperature_sources)
.attr("fill", colors.natBg)
.attr("d", areaNat);

g.append("path")
.datum(temperature_sources)
.attr("fill", colors.ghgBg)
.attr("d", areaGhg);

g.append("path")
.datum(temperature_sources)
.attr("fill", "#666")
.attr("fill-opacity", 0.1)
.attr("d", areaSsp245);

g.append("path")
.datum(temperature_sources)
.attr("stroke", colors.aer)
.attr("fill", "none")
.attr("d", lineAer);

g.append("path")
.datum(temperature_sources)
.attr("stroke", colors.nat)
.attr("fill", "none")
.attr("d", lineNat);

g.append("path")
.datum(temperature_sources)
.attr("stroke", colors.ghg)
.attr("fill", "none")
.attr("d", lineGhg);

g.append("path")
.datum(temperature_sources)
.attr("stroke", "#aaa")
.attr("fill", "none")
.attr("d", lineSsp245);

g.append("path")
.datum(temperature_sources)
.attr("stroke", "#2a2a2a")
.attr("stroke-width", 2)
.attr("fill", "none")
.attr("d", lineObs);

g.append("g").attr("transform", "translate(4)").selectAll(".label")
.data(labelData)
.join("text")
.attr("class", "label")
.attr("fill", d => colors[d.key])
.attr("font-weight", d => d.key === "obs" ? "bold" : "normal")
.attr("x", x(x.domain()[1]))
.attr("y", d => y(d.value))
.html(d => d.label)
return svg.node();
}
Insert cell
Insert cell
css = `
.axis .tick text {
font-family: ${franklinLight};
font-size: 14px;
fill: #666666;
}
.axis .tick line {
shape-rendering: crispEdges;
stroke: #d5d5d5;
}
.axis.y-axis .domain {
display: none;
}
.axis.x-axis .domain {
shape-rendering: crispEdges;
stroke: #d5d5d5;
}
.baseline {
shape-rendering: crispEdges;
stroke: #d5d5d5;
}
.label {
font-family: ${franklinLight};
}
`
Insert cell
colors = ({
aer: "#E69D67",
ghg: "#BF6136",
nat: "#6E86AA",
obs: "#2a2a2a",
ssp245: "#666666",
aerBg: "rgba(230, 157, 103, 0.1)",
ghgBg: "rgba(191, 97, 54, 0.1)",
natBg: "rgba(110, 134, 170, 0.1)",
})
Insert cell
Insert cell
areaAer = d3.area()
.x(d => x(d.year))
.y0(d => y(d.gsta_blue_shading_bottom_hist_aer))
.y1(d => y(d.gsta_blue_shading_top_hist_aer))
Insert cell
areaGhg = d3.area()
.x(d => x(d.year))
.y0(d => y(d.gsta_red_shading_bottom_hist_ghg))
.y1(d => y(d.gsta_red_shading_top_hist_ghg))
Insert cell
areaNat = d3.area()
.x(d => x(d.year))
.y0(d => y(d.gsta_green_shading_bottom_hist_nat))
.y1(d => y(d.gsta_green_shading_top_hist_nat))
Insert cell
areaSsp245 = d3.area()
.x(d => x(d.year))
.y0(d => y(d.gsta_grey_shading_bottom_hist_ssp245))
.y1(d => y(d.gsta_grey_shading_top_hist_ssp245))
Insert cell
lineAer = d3.line()
.x(d => x(d.year))
.y(d => y(d.gsta_blue_line_hist_aer))
Insert cell
lineGhg = d3.line()
.x(d => x(d.year))
.y(d => y(d.gsta_red_line_hist_ghg))
Insert cell
lineNat = d3.line()
.x(d => x(d.year))
.y(d => y(d.gsta_green_line_hist_nat))
Insert cell
lineObs = d3.line()
.x(d => x(d.year))
.y(d => y(d.gsta_black_obs))
Insert cell
lineSsp245 = d3.line()
.x(d => x(d.year))
.y(d => y(d.gsta_grey_line_hist_ssp245))
Insert cell
// Total warming
temperature_sources[temperature_sources.length - 1].gsta_black_obs
Insert cell
Insert cell
x = d3.scaleLinear(d3.extent(temperature_sources, d => d.year), [ 0, chartwidth ])
Insert cell
y = d3.scaleLinear([-1.5, 2.5], [ chartheight, 0 ])
Insert cell
Insert cell
margin = ({left: 40, right: 136, top: 5, bottom: 21})
Insert cell
basewidth = 800
Insert cell
chartwidth = basewidth - margin.left - margin.right
Insert cell
chartheight = basewidth * 0.5 - margin.top - margin.bottom
Insert cell
Insert cell
temperature_sources = rows
.slice(54)
.map(row => {
const o = {};
row
.split(",")
.forEach((v, i) => {
o[cols[i]] = +v;
});
return o;
})
.filter(d => d.year)
Insert cell
rows = gmst_anomalies_timeseries.split("\n")
Insert cell
cols = d3
.groups(
rows.slice(10, 52),
(_, i) => Math.floor(i / 3)
)
.map(([i, entries]) => entries[0].split(",")[2].toLowerCase())
Insert cell
gmst_anomalies_timeseries = FileAttachment("gmst_anomalies_timeseries.csv").text()
Insert cell
labelData = [
{
key: "ghg",
label: "Greenhouse gases",
value: 1.55,
},
{
key: "ssp245",
label: `Combined`,
value: 0.9
},
{
key: "obs",
label: "Observations",
value: 1.2
},
{
key: "nat",
label: "Natural causes",
value: 0
},
{
key: "aer",
label: "Aerosols",
value: -0.5
}
]
Insert cell
Insert cell
import { franklinLight } from "@climatelab/fonts@46"
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