Public
Edited
Sep 29, 2023
2 forks
Insert cell
Insert cell
Insert cell
Insert cell
value = 37
Insert cell
<p>This is some <b>HTML</b> code with embedded ${value} data</p>
Insert cell
Insert cell
<svg width="400" height="200" style="border:1px solid black">
<circle cx="100" cy="100" r="50" fill="red"><title>Circle!</title></circle>
<rect class="fancy" x="100" y="70" width="200" height="50" fill="green"/>
<text x="50" y="50">Hello World</text>
<path d="M10,60 L40,90 L60,10 L190,10" stroke="black" fill="none">
</svg>
Insert cell
Insert cell
<style type="text/css">
.fancy { fill:steelblue; fill-opacity:0.75; stroke:none; }
</style>
Insert cell
Insert cell
// D3 is automatically imported in Observable
//d3 = require("d3")
d3.version
Insert cell
Insert cell
d3
.select("svg")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 50)
.attr("height", 50).null
Insert cell
Insert cell
data1 = await FileAttachment("States2010.csv").csv({ typed: true })
Insert cell
data = (await FileAttachment("States2010.csv").csv({ typed: true })).sort(
(a, b) => a.PercentCollegeGrad - b.PercentCollegeGrad
)
Insert cell
Insert cell
Insert cell
chart11 = {
// Define SVG tag
let svg = d3
.create("svg")
.attr("width", 800) // border goes outside of this, thus border adds to total width.
.attr("height", 300)
//.attr("viewBox", [0, 0, 800, 300]) //viewBox adds a transform that auto scales to the window width,
.style("border", "1px solid black"); // minus the border width.
// add a title
let text = svg
.append("text")
.attr("x", 10)
.attr("y", 20)
.style("font", "12px Arial")
.html("Chart title here");

// MARKS & CHANNELS (2 options:)
//// Single Mark Method: map all data rows to one big complex mark (like a path or polyline)
let path = svg
.append("path")
.attr("d", d3.line()(linedata))
.attr("stroke", "black")
.attr("fill", "none");

//// Multi-Mark Method: map each data row to a mark (like a rect)
let bars = svg
.selectAll("rect")
.data(data) // bind data rows to rects
.join("rect") // creates new Rects for each data row (handles enter, update, and exit)
// Multi-mark Channels: maps data columns to rect attributes
.attr("x", (r, i) => i * 15) // map to pixels
.attr("width", 13)
//.attr("y", 0)
.attr("y", (r) => 300 - (r.PercentCollegeGrad / 50) * 300) // map to pixels
.attr("height", (r) => (r.PercentCollegeGrad / 50) * 300)
.style("fill", "steelblue");
//.style("fill", (r) => d3.hsl(200, 0.5, 1 - r.IncomePerCapita / 85000)) // Blue Luminance scale

// Tooltips
bars
.append("title") // adds the title tag inside the rect tag
.text((r) => r.Name + " " + r.PercentCollegeGrad);

// return SVG tag
return svg.node();
}
Insert cell
linedata = data.map((r, i, a) => [
i * 15,
300 - (r.PercentCollegeGrad / 50) * 300
])
Insert cell
d3.line()(linedata)
Insert cell
d3.extent(data, (d) => d.PercentCollegeGrad)
Insert cell
data.length
Insert cell
d3.extent(data, (d) => d.IncomePerCapita)
Insert cell
Insert cell
Insert cell
chart2 = {
// copy and paste from above
}
Insert cell
Legend(cScale, { title: "Income Per Capita ($)" })
Insert cell
//// = new stuff
chart22 = {
// Define SVG tag
let svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.style("border", "1px solid black");
let text = svg
.append("text")
.attr("x", 50)
.attr("y", 20)
.style("font", "12px Arial")
.html("Chart Title here");

//// Draw axes
drawAxis(svg, yScale, "left", margin.left - 3, "Percent College Graduates");
drawAxis(svg, xScale, "bottom", height - margin.bottom + 3, "States");
//svg
// .append("g")
// .attr("transform", `translate(${margin.left - 3}, 0)`) //located at x=0 by default
// .call(d3.axisLeft(yScale));
//svg
// .append("g")
// .attr("transform", `translate(0, ${height - margin.bottom + 3})`) //located at y=0 by default
// .call(d3.axisBottom(xScale));

// MARKS: maps data rows to rects
let bars = svg
.selectAll("rect")
.data(data, (r) => r.Abbrev)
.join("rect") // creates new Rects for each data row

//// CHANNELS: maps data columns to rect attributes
.attr("x", (r) => xScale(r.Abbrev))
.attr("width", xScale.bandwidth() - 1)
.attr("y", (r) => yScale(r.PercentCollegeGrad))
.attr("height", (r) => yScale(0) - yScale(r.PercentCollegeGrad) + 1)
//.style("fill", "steelblue")
.style("fill", (r) => cScale(r.IncomePerCapita));

// Tooltips
bars
.append("title") // adds the title tag inside the rect tag
.text((r) => r.Name + " " + r.PercentCollegeGrad);

// return SVG tag
return svg.node();
}
Insert cell
yScale = d3
.scaleLinear()
.domain([0, 50])
.range([height - margin.bottom, margin.top]) // flip y axis
Insert cell
xScale = d3
.scaleBand()
.domain(data.map((d) => d.Abbrev)) // map categorical bands by Abbrevs
.range([margin.left, width - margin.right])
Insert cell
cScale = d3.scaleSequential(d3.interpolateBlues).domain([0, 65000])
Insert cell
Insert cell
Insert cell
// predefined by Observable:
width
Insert cell
Insert cell
import { drawAxis } from "@chrislnorth/simple-axis-drawing"
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