Public
Edited
Apr 16
Insert cell
Insert cell
Insert cell
<svg width="1100" height="1100">
<style>
/* edit these styles as you need - this is a starting point*/
rect {stroke: white; stroke-width: 2px;}
text {fill: white; font-family: 'Rajdhani', sans-serif;}
.maintitle {font-size: 39px; fill: black;}
.mainsubtitle {font-size: 18px; fill: black;}
.title {text-anchor: end; font-size: 32px;}
.subtext1, .subtext2, .subtext3 {}
.footprint {font-size: 17px;}
line {stroke: white; stroke-width: 2px;}
</style>

<text x="0" y="27" class="maintitle">Land Guzzlers</text>
<text x="0" y="50" class="mainsubtitle">The ecological footprints of our pets can make SUVs look positively eco-friendly </text>

<!-- the rest will be drawn by the data using D3 below -->
</svg>
Insert cell
Insert cell
Insert cell
colors = ["#a5620b","#c29657","#cc1f5e","#a71949","#f7991d","#231f20"]
// in order Large Dog to Hamster.Reference as colors[i]
Insert cell
land_guzzlers = FileAttachment("land_guzzlers.csv").csv()
Insert cell
// I flipped the order becuase they were stacking backwards (I was only seeing the largest)
land_guzzlers.sort((a, b) => b.footprint - a.footprint);
Insert cell
{
// select the cell called svgContainer and make it a d3 object.
let landguzzlersViz = d3.select(svgContainer)
// draw Rectangles first - get this section to work before you try the others.
landguzzlersViz.selectAll("rect")
.data(land_guzzlers)
.join("rect")
.attr("width", d => Math.sqrt(d.footprint) * 1000) // *1000 so it fills the SVG
.attr("height", d => Math.sqrt(d.footprint) * 1000)
.attr("x", 0) //I want to keep it against the left side
.attr("y", (d, i) => 1100 - Math.sqrt(d.footprint) * 1000) // Stacks them from bottom left FORMULA: ToalHeight-Height of each sq
.style("fill", (d, i) => colors[i]);

// // Now add the Large Dog, Toyota, etc. titles
// // notice that I'm selectingAll objects of a class called .title to only get those text elements.
landguzzlersViz.selectAll(".title")
.data(land_guzzlers)
.join("text")
.attr("x", d => {
if (d['title'] === "HAMSTER") // since HAMSTER is different
{return Math.sqrt(d.footprint) * 1000 + 125}
else
{return Math.sqrt(d.footprint) * 1000-5}})
.attr("y", d => 1100 - Math.sqrt(d.footprint) * 1000 + 30) //The plus 30 make the title in each square, w/o its on top
.text(d => d['title']) // this is the text contents, eg. LARGE DOG
.attr("class", "title"); // tag it with the style class 'title' so the selectAll above works.

// // Now the rotated Eco-Footprint text and values. Note the rotation transform.
landguzzlersViz.selectAll(".footprint") // selecting a .class of objects again.
.data(land_guzzlers)
.join("text")
.attr("x", d => {
if (d['title'] === "HAMSTER") // since HAMSTER is different
{return Math.sqrt(d.footprint) * 1000}
else {return Math.sqrt(d.footprint) * 1000- 15}})
.attr("y", d => 1100 - Math.sqrt(d.footprint) * 1000 + 45)
.text((d, i) => (i !== 3) ? "Eco-footprint: " + d['footprint'] + " hectores" : "") // hides text from VOLKSWAGEN sq.
.attr("transform", (d,i,nodes) => {
if (d['title'] === "HAMSTER")
{return } //dont want to rotate for HAMSTER
else
{return "rotate(90 " + nodes[i].getAttribute("x") + " " + nodes[i].getAttribute("y") + ")";} })
// ^^ OK, so you would not have gotten this one on your own easily. See if you can figure it out.
// transform is "rotate(angle xPivotPoint yPivotPoint)" This is an SVG transform.
.attr("class", "footprint"); // tag it with the style class 'footprint'

// ... what other objects do we need and how do we get them. Use the same approaches.
// My code to add the subtitiles
landguzzlersViz.selectAll(".subtitle")
.data(land_guzzlers)
.join("text")
.attr("x", d => Math.sqrt(d.footprint) * 1000 - 20)
.attr("y", d => 1100 - Math.sqrt(d.footprint) * 1000+ 50)
.text(d => d['subtitle'])
.attr("text-anchor", "end")
.attr("class", "subtitle");
landguzzlersViz.selectAll(".subtitle2")
.data(land_guzzlers)
.join("text")
.attr("x", d => Math.sqrt(d.footprint) * 1000-20)
.attr("y", d => 1100 - Math.sqrt(d.footprint) * 1000+ 70)
.text(d => d['subtitle2'])
.attr("text-anchor", "end")
.attr("class", "subtitle2");
landguzzlersViz.selectAll(".subtitle3")
.data(land_guzzlers)
.join("text")
.attr("x", d => Math.sqrt(d.footprint) * 1000-20)
.attr("y", d => 1100 - Math.sqrt(d.footprint) * 1000+ 90)
.text(d => d['subtitle3'])
.attr("text-anchor", "end")
.attr("class", "subtitle3");
}

//Things that got me stuck: splitting up the line of the eco-footprint for HAMSTER. Drawing the white lines under MEDIUM-SIZE CRUISER and MEDIUM SIZED DOG
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
<link href="https://fonts.googleapis.com/css?family=Rajdhani" rel="stylesheet">
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