Published
Edited
Sep 27, 2020
6 stars
Insert cell
Insert cell
Insert cell
import { hexdata } from '@enjalot/purpleair-historical-data'
Insert cell
//import {hexdata} from '@enjalot/smoke-forecast'
Insert cell
hexdata
Insert cell
groupedData = d3.group(hexdata, d => d.day)
Insert cell
times = Array.from(groupedData.keys())
Insert cell
timeData = groupedData.get(currentTime)
Insert cell
points = timeData.map(d => [d.lng, d.lat, d.pm1])
Insert cell
Insert cell
Insert cell
Insert cell
mapSVG = svg`<svg width=${width} height=${height}>
<defs>
<clipPath id="californiaClip">
<path></path>
</clipPath>
</defs>
<path class="state"></path>
<g class="voronoi" transform="rotate(-70, ${width/2},${height/2})scale(1.25)translate(-70,-70)"></g>
</svg>`
Insert cell
projection = d3.geoAlbersUsa()
// magically fits map geography to width/height!
.fitSize([width, height], california[0])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
path = d3.geoPath(projection)
Insert cell
colorPM1 = d3.scaleLinear()
.domain([0,50, 100, 150, 200, 250])
// colorPM1 = d3.scaleThreshold()
// .domain([50, 100, 150, 200, 250])
.range(["green", "yellow", "orange", "red", "maroon", "maroon"])
Insert cell
round5 = (n) => Math.round(n/5)*5
Insert cell
round5(11)
Insert cell
function render(svg) {
let svgSelection = d3.select(svg)
// california is an array with 1 element in it (the GeoJSON of its boundaries)
// the path function takes in a GeoJSON element and returns an SVG path string
// we can use this both to define the clippath and draw a boundary
let cali = path(california[0])

svgSelection.select("#californiaClip")
.select("path")
.attr('d', cali)
.attr('stroke', 'black')
.attr('fill', 'none');

// create the outline of california to clip our voronoi
// using https://observablehq.com/@manishearth/uc-california-voronoi-map
//what are defs
svgSelection.select("path.state")
// whats the dif between .data and .datum?
// When do you use each?
.attr("fill", "none")
// .attr("stroke", "#111")
.attr("stroke-width", 6)
.attr("stroke-linejoin", "round")
.attr("d", cali);

svgSelection.select("g.voronoi")
// .append("g")
.attr("stroke", "none")
.attr("pointer-events", "all")
.selectAll("path")
.data(d3.geoVoronoi().polygons(points).features)
.join("path")
.attr("d", d3.geoPath(projection))
.attr("fill", d => colorPM1(round5(d.properties.site[2])))
.attr("stroke", d => colorPM1(round5(d.properties.site[2])))
// .attr("stroke", "black")
.attr("clip-path", "url(#californiaClip)");

return svgSelection;
}
Insert cell
Insert cell

rendered = render(mapSVG)
Insert cell
height = 600
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