Public
Edited
Apr 17, 2023
Insert cell
Insert cell
<svg width="1000" height="1015">
<!-- Styles -->
<style>
rect {
stroke: white;
stroke-width: 2px;
x="10"
}
text {
font-family: 'Noto Sans', sans-serif;
font-weight: 300;
}
path {stroke: #FFFFFF;
fill: none;}
tspan {baseline-shift: super;
font-size: 10px}
.title {x="10";
fill: #000000}
.square_title {fill: #FFFFFF;}
.inner {text-anchor: end}
.eco {writing-mode: tb;
fill: #FFFFFF;
font-size: 20px}
.detail1 {fill: #FFFFFF;
font-size: 18px;
text-anchor: end}
.detail2 {fill: #FFFFFF;
font-size: 18px;
text-anchor: end}
.detail3 {fill: #FFFFFF;
font-size: 18px;
text-anchor: end}
.large_dog {font-size: 32px}
.medium_dog {font-size: 30px}
.toyota {font-size: 28px}
.volkswagen {font-size: 26px;
opacity: .5}
.cat {font-size: 26px}
.hamster {font-size: 24px}
.eco_hamster1 {font-size: 20px}
.eco_hamster2 {font-size: 20px}
</style>

<!-- TITLES -->
<text font-size=36px y="31" class="title">Land guzzlers</text>
<text font-size=19px y="56" class="title">The ecological footprints of our pets can make SUVs look positively eco-friendly</text>
</svg>
Insert cell
<head>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@300&display=swap" rel="stylesheet">
</head>
Insert cell
Insert cell
landguzzlers = d3.select(svgContainer) // selects the cell called svgContainer and make it a d3 object.
Insert cell
Insert cell
data = FileAttachment("land_guzzlers.csv").csv()
Insert cell
Insert cell
data.forEach(d => {
d["pixel_footprint"] = (d["footprint"]**.5) * 896.25483389098628;
})
Insert cell
Insert cell
title_size = (text) => {
if (text == "LARGE DOG") {return 32;}
else if (text == "MEDIUM-SIZED DOG") {return 30;}
else if (text == "TOYOTA LAND CRUISER") {return 28;}
else if (text == "VOLKSWAGEN GOLF") {return 26;}
else if (text == "CAT") {return 26;}
else if (text == "HAMSTER") {return 24;}
}
Insert cell
title_class = (text) => {
if (text == "LARGE DOG") {return "inner square_title large_dog";}
else if (text == "MEDIUM-SIZED DOG") {return "inner square_title medium_dog";}
else if (text == "TOYOTA LAND CRUISER") {return "inner square_title toyota";}
else if (text == "VOLKSWAGEN GOLF") {return "inner square_title volkswagen";}
else if (text == "CAT") {return "inner square_title cat";}
else if (text == "HAMSTER") {return "square_title hamster";}
}
Insert cell
data.forEach(d => {
d["title_class"] = title_class(d["title"])
})
Insert cell
data.forEach(d => {
d["title_size"] = title_size(d["title"])
})
Insert cell
{
let colors = ["#a5620b", "#c29657", "#cc1f5e", "#a71949", "#f7991d", "#231f20"]
let viz_height = landguzzlers.attr("height") - 5
let viz_width = landguzzlers.attr("width")

// creating the squares
landguzzlers.selectAll("rect")
.data(data)
.join("rect")
.attr("y", d => viz_height - d["pixel_footprint"])
.attr("width", d => d["pixel_footprint"])
.attr("height", d => d["pixel_footprint"])
.style("fill", (d, i) => colors[i]);

// creating the titles within the squares
landguzzlers.selectAll(".square_title")
.data(data)
.join("text")
.text(d => d["title"])
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"])
.attr("x", d => d["pixel_footprint"] - 5)
.attr("class", d => d["title_class"]);

// creating the eco-footprint subtitles (except for hamster and volkswagen)
landguzzlers.selectAll(".eco")
.data(data.filter(d => d["title"] != "HAMSTER").filter(d => d["title"] != "VOLKSWAGEN GOLF"))
.join("text")
.text(d => "Eco-footprint: " + d["footprint"] + " hectares")
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"] + 5)
.attr("x", d => d["pixel_footprint"] - 15)
.attr("class", "eco");

// creating the subtitles
landguzzlers.selectAll(".detail1")
.data(data)
.join("text")
.text(d => d["subtitle"])
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"] + 25)
.attr("x", d => d["pixel_footprint"] - 30)
.attr("class", "detail1");

landguzzlers.selectAll(".detail2")
.data(data)
.join("text")
.text(d => d["subtitle2"])
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"] + 42)
.attr("x", d => d["pixel_footprint"] - 30)
.attr("class", "detail2");

landguzzlers.selectAll(".detail3")
.data(data)
.join("text")
.text(d => d["subtitle3"])
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"] + 60)
.attr("x", d => d["pixel_footprint"] - 30)
.attr("class", "detail3");
// dealing with "Hamster" title
landguzzlers.selectAll(".hamster")
.data(data)
.join("text")
.attr("dx", 10);

// dealing with Hamster subtitles
landguzzlers.selectAll(".eco_hamster1")
.data(data.filter(d => d["title"] == "HAMSTER"))
.join("text")
.text("Eco footprint:")
.attr("x", d => d["pixel_footprint"] + 5)
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"] + 20)
.attr("class", "eco_hamster1 square_title");

landguzzlers.selectAll(".eco_hamster2")
.data(data.filter(d => d["title"] == "HAMSTER"))
.join("text")
.text(d => d["footprint"] + " hectares")
.attr("x", d => d["pixel_footprint"] + 5)
.attr("y", d => viz_height - d["pixel_footprint"] + d["title_size"] + 40)
.attr("class", "eco_hamster2 square_title");
}
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