Public
Edited
May 15, 2023
2 forks
Importers
91 stars
Insert cell
Insert cell
Insert cell
projection = d3.geoAlbers()
.fitSize([mapWidth, mapHeight], geoJsonUsa);
Insert cell
{
const svg = d3.select(DOM.svg(mapWidth, mapHeight));
svg.selectAll("path")
.data(geoJsonUsa.features)
.enter().append("path")
.attr("fill", "#eee")
.attr("stroke", "#bbb")
.attr("d", d3.geoPath(projection));
return svg.node();
}
Insert cell
Insert cell
scaleBar = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight]);
Insert cell
{
const svg = d3.select(DOM.svg(mapWidth, mapHeight));
svg.selectAll("path")
.data(geoJsonUsa.features)
.enter().append("path")
.attr("fill", "#eee")
.attr("stroke", "#bbb")
.attr("d", d3.geoPath(projection));
// Call the scale bar like this.
svg.append("g")
.call(scaleBar);
return svg.node();
}
Insert cell
Insert cell
scaleBarPositioned = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(.05)
.top(.85)
.tickFormat(d3.format(",")); // A formatter function adds a comma to "1,000"
Insert cell
Insert cell
Insert cell
scaleBarWapo = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(left)
.top(top)
.units(d3.geoScaleMiles) // The units will be miles instead of kilometers
.distance(500) // The distance of the scale bar
.label("500 miles") // The label on top of the scale bar
.labelAnchor("middle") // The position of the label (you can also pass "start" and "end")
.tickSize(null) // The height of the bar
.tickValues(null); // The tick values below the bar will be removed
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
scaleBarTop = d3.geoScaleBar()
.orient(d3.geoScaleTop) // The other orientation is d3.geoScaleBottom, which is the default
.top(.1)
.left(.5)
.distance(250)
.label(null)
.tickPadding(3) // How far the tick text labels are from the lines
.tickFormat((d, i, e) => i === e.length - 1 ? `${d} Kilometers` : d)
.tickValues([0, 250])
Insert cell
Insert cell
scaleBarBottom = d3.geoScaleBar()
.units(d3.geoScaleMiles) // Other options are d3.geoScaleFeet, d3.geoScaleKilometers, and d3.geoScaleMeters
.orient(d3.geoScaleBottom) // Redundant as this is the default
.top(.1)
.left(.5)
.distance(250)
.label(null)
.tickPadding(3) // How far the tick text labels are from the lines
.tickFormat((d, i, e) => i === e.length - 1 ? `${d} Miles` : d)
.tickValues([0, 250]);
Insert cell
Insert cell
projectionIndia = proj4d3(`+proj=aea +lat_2=12 +lat_1=28 +lat_0=20 +lon_0=78 +x_0=2000000 +y_0=2000000`)
Insert cell
Insert cell
Insert cell
scaleBarZoom = d3.geoScaleBar()
.zoomClamp(false) // Set this to true to keep the bar's width constant
.projection(projection)
.size([mapWidth, mapHeight])
.left(.05)
.top(.85)
.tickFormat(d => d3.format(",")(+d.toFixed(1))); // A formatter function rounds the tick values and adds a comma to "1,000"
Insert cell
{
const wrapper = d3.select(DOM.element("div"));
const svg = wrapper.append("svg")
.attr("width", mapWidth)
.attr("height", mapHeight);

const g = svg.append("g");
g.selectAll("path")
.data(geoJsonUsa.features)
.enter().append("path")
.attr("fill", "#eee")
.attr("stroke", "#bbb")
.attr("d", d3.geoPath(projection));
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);
})
);
wrapper.append("div")
.style("font-family", "sans-serif")
.style("font-size", "13px")
.style("color", "#555")
.text("You can zoom and pan this map.");
return wrapper.node();
}
Insert cell
Insert cell
scaleBarWapoZoom = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(.1)
.top(.9)
.units(d3.geoScaleMiles)
.distance(500)
.label("500 miles")
.labelAnchor("middle")
.tickSize(null)
.tickValues(null);
Insert cell
Insert cell
Insert cell
scaleBarBottomZoom = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(.1)
.top(.9)
.units(d3.geoScaleMiles)
.label(null)
.tickPadding(2)
.tickSize(0)
.tickFormat((d, i, e) => i === e.length - 1 ? `${d} mi.` : d)
.zoomClamp(false);
Insert cell
scaleBarTopZoom = d3.geoScaleBar()
.projection(projection)
.size([mapWidth, mapHeight])
.left(.1)
.top(.9)
.orient(d3.geoScaleTop)
.label(null)
.tickPadding(2)
.tickSize(0)
.tickFormat((d, i, e) => i === e.length - 1 ? `${d} km.` : d)
.zoomClamp(false);
Insert cell
Insert cell
Insert cell
Insert cell
scaleBarTransition = d3.geoScaleBar()
.top(.1)
.left(.01)
.tickFormat(d3.format(","));
Insert cell
Insert cell
Insert cell
scaleBarMoon = d3.geoScaleBar()
.radius(1737.4) // The radius of the moon is 1,737.4 kilometers
.top(.9)
.left(.05);
Insert cell
Insert cell
Insert cell
scaleBarDc = d3.geoScaleBar()
.top(.9)
.left(.05)
.radius(6967419.888)
.label("Yards")
// .units({units: "yards", radius: 6967419.888}) // Will do the same as the previous two lines
.distance(mapWidth <= 400 ? 1200 : 1000)
.tickFormat(d3.format(","));
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more