Public
Edited
Jan 25, 2023
Insert cell
Insert cell
Insert cell
geoJsonUsa = FileAttachment("usa.json").json()
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
{
const wrapper = d3.select(DOM.element("div"));

const svg = wrapper
.append("svg")
.attr("width", mapWidth)
.attr("height", mapHeight);

const g = svg.append("g");

// add State paths
g.selectAll("path")
.data(geoJsonUsa.features)
.enter()
.append("path")
.attr("fill", "#eee")
.attr("stroke", "#bbb")
.attr("d", d3.geoPath(projection));

// add shooting points
g.selectAll("circle")
.data(points)
.enter()
.append("circle")
.attr("cx", function(d) {
console.log(projection(d));
return projection(d)[0];
})
.attr("cy", function(d) {
return projection(d)[1];
})
.attr("r", "2px")
.attr("fill", "red");

// add scale bar
const bar = svg.append("g").call(scaleBarWapoZoom);
bar.select(".domain").style("stroke-width", 1.5);

// Call d3.zoom on your SVG element
svg.call(
d3
.zoom()
.scaleExtent([1, 10])
.translateExtent([[0, 0], [mapWidth, mapHeight]])
.on("zoom", _ => {
const t = d3.event.transform;

g.attr("transform", t);

scaleBarWapoZoom
.label(
`${Math.round(
scaleBarWapoZoom.distance() / t.k
)} ${scaleBarWapoZoom.units()}`
)
.zoomFactor(t.k);

bar.call(scaleBarWapoZoom);
})
);

// add slider
var moving = false;
var currentValue = 0;
var targetValue = width;

var playButton = d3.select("#play-button");

var x = d3
.scaleTime()
.domain([min_date, max_date])
.range([0, targetValue])
.clamp(true);

var slider = svg
.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + margin.left + "," + height / 5 + ")");

slider
.append("line")
.attr("class", "track")
.attr("x1", x.range()[0])
.attr("x2", x.range()[1])
.select(function() {
return this.parentNode.appendChild(this.cloneNode(true));
})
.attr("class", "track-inset")
.select(function() {
return this.parentNode.appendChild(this.cloneNode(true));
})
.attr("class", "track-overlay")
.call(
d3
.drag()
.on("start.interrupt", function() {
slider.interrupt();
})
.on("start drag", function() {
currentValue = d3.event.x;
update(x.invert(currentValue));
})
);

slider
.insert("g", ".track-overlay")
.attr("class", "ticks")
.attr("transform", "translate(0," + 18 + ")")
.selectAll("text")
.data(x.ticks(10))
.enter()
.append("text")
.attr("x", x)
.attr("y", 10)
.attr("text-anchor", "middle")
.text(function(d) {
return formatDateIntoYear(d);
});

var handle = slider
.insert("circle", ".track-overlay")
.attr("class", "handle")
.attr("r", 9);

var label = slider
.append("text")
.attr("class", "label")
.attr("text-anchor", "middle")
.text(formatDate(min_date))
.attr("transform", "translate(0," + -25 + ")");

// plot
function update(h) {
// update position and text of label according to slider scale
handle.attr("cx", x(h));
label.attr("x", x(h)).text(formatDate(h));

// // filter data set and redraw plot
// var newData = dataset.filter(function(d) {
// return d.date < h;
// });
// drawPlot(newData);
}

return wrapper.node();
}
Insert cell
Insert cell
Insert cell
margin = {
const margin = {
top: 50,
right: 50,
bottom: 0,
left: 50
};
return margin;
}
Insert cell
width = 1000 - margin.left - margin.right
Insert cell
height = 600 - margin.top - margin.bottom
Insert cell
formatDate = d3.timeFormat("%b %Y")
Insert cell
formatDateIntoYear = d3.timeFormat("%Y")
Insert cell
projection = d3.geoAlbersUsa().fitSize([mapWidth, mapHeight], geoJsonUsa)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// uncomment to see raw HTML from result
// txt.parse.text["*"]
Insert cell
Insert cell
md`
getting data from shootings table in usable form
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
dates = data.map(shooting => {
return shooting.date;
})
Insert cell
max_date = dates[dates.length - 1]
Insert cell
min_date = dates[0]
Insert cell
md`
# Getting Data
`
Insert cell
md`
#### Getting all data from shootings`
Insert cell
Insert cell
md`
## Imports
`
Insert cell
d3 = require("d3@5", "d3-geo-scale-bar@1.0.2")
Insert cell
d3_time_format = require("d3-time-format")
Insert cell
import { legend } from "@d3/color-legend"
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