Published
Edited
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
// Set dimensions with view box
//const svg = d3.create("svg")
//.attr("viewBox", [0, 0, 975, 610]);
// Const svg with select
// const svg = d3.select(DOM.svg(mapWidth, mapHeight));
// Draw canvas
const wrapper = d3.select(DOM.element("div"));
const svg = wrapper.append("svg")
.attr("width", mapWidth)
.attr("height", mapHeight);
const g = svg.append("g");
// call the scale bar function without posistioning
// svg.append("g")
// .call(scaleBar);
// use positioning function
// svg.append("g")
// .call(scaleBarPositioned);
// Use zoom-responsive bar
const bar = svg.append("g")
.attr("class", "scale-bar-wrapper")
.call(scaleBarZoom);
// Call d3.zoom on your SVG element
svg.call(d3.zoom()
.scaleExtent([1, 10])
.translateExtent([[0, 0], [mapWidth, mapHeight]])
.on("zoom", event => {
const t = event.transform;
g.attr("transform", t);
// Pass the k property of the zoom's transform
// to the scale bar's scaleFactor.
// Then call the scaleBar again.
scaleBarZoom.zoomFactor(t.k);
bar.call(scaleBarZoom);
})
);
//draw US
g.selectAll("path")
.data(geoJsonUsa.features)
.enter().append("path")
.attr("fill", "#eee")
.attr("stroke", "#bbb")
.attr("d", d3.geoPath(projection));
//draw bubbles
let propCircles = g
.selectAll('circle')
.data(data)
.enter()
.append("circle")
//add some styles
.style("stroke", "black")
.style("stroke-width", 0.5)
.style("fill", "brown")
.style("opacity", "0.8")
.style("pointer-events", "none")
.attr("r", d => toRadius(d))
//use projection to display bubbles
.attr("cx", d => {
if (d) {
if (d[date] > 0) {
let coordinates = [d.lng, d.lat];
return projection(coordinates)[0];
}
}
})
.attr("cy", d => {
if (d) {
if (d[date] > 0) {
let coordinates = [d.lng, d.lat];
return projection(coordinates)[1];
}
}
});
//Add a legend for the size of the bubbles
const legend = svg.append("g")
.attr("fill", "#777")
.attr("transform", "translate(915,608)")
.attr("text-anchor", "middle")
.style("font", "10px sans-serif")
.selectAll("g")
.data(circleScale.ticks(4).slice(1))
.join("g");

legend.append("circle")
.attr("fill", "none")
.attr("stroke", "#ccc")
.attr("cy", d => -circleScale(d))
.attr("r", circleScale);

legend.append("text")
.attr("y", d => -2 * circleScale(d))
.attr("dy", "1.3em")
.text(circleScale.tickFormat(4, "s"));
return wrapper.node();
}
Insert cell
Insert cell
geoJsonUsa = FileAttachment("usa.json").json()
Insert cell
Insert cell
csvData = FileAttachment("cumNDdeaths.csv")
Insert cell
data = d3.csvParse(await csvData.text())
Insert cell
Insert cell
mapWidth = 975
Insert cell
mapHeight = 610
Insert cell
scaleBar = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight]);
Insert cell
scaleBarPositioned = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(.05)
.top(.85)
.distance(1000) // Sets the distance represented by the bar to 1000 km
.tickFormat(d3.format(",")); // A formatter function adds a comma to "1,000"
Insert cell
scaleBarZoom = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(.05)
.top(.85)
.tickFormat(d => d3.format(",")(Math.round(d))); // A formatter function rounds the tick values and adds a comma to "1,000"
Insert cell
Insert cell
toRadius = function(d) {
if (d) {
return circleScale(d[date]);
}
}
Insert cell
format = d3.format(",.0f")
Insert cell
circleScale = d3
.scaleSqrt()
.domain(numbersExtent)
.range([2, 50])
Insert cell
numbersExtent = [0, 71]
Insert cell
projection = d3.geoAlbers()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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