Published
Edited
Nov 17, 2020
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mColorScale(svgAngle([Math.random(),Math.random()]))
Insert cell
usMap
Insert cell
WIDTH = 500
Insert cell
HEIGHT = 400
Insert cell
Insert cell
Insert cell
projection([ -129.55, 48.38])
Insert cell
Insert cell
Insert cell
processedWindData[0]
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
{
const f = renderingType == "Canvas"? canvasMap : svgMap;
return f();
}
Insert cell
canvasMap = ()=>{
const projection = d3.geoEquirectangular()

const points = {type: "MultiPoint", coordinates: mData.map(d => [d.longitude, d.latitude])};
const margin = 10;
const [[x0, y0], [x1, y1]] = d3.geoPath(projection.fitWidth(width - margin * 2, points)).bounds(points);
const [tx, ty] = projection.translate();
let height = Math.ceil(y1 - y0);
projection.translate([tx + margin, ty + margin]);
height = height + margin * 2;

const context = DOM.context2d(width, height);
const path = d3.geoPath(projection, context);
context.canvas.style.maxWidth = "100%";
context.fillRect(0, 0, width, height);
context.strokeStyle = "#eee";
context.lineWidth = 1.5;
context.lineJoin = "round";
context.beginPath(), path(mLand), context.stroke();
for (const {longitude, latitude, speed, dir} of mData) {
context.save();
context.translate(...projection([longitude, latitude]));
context.scale(areaScale(speed), areaScale(speed));
context.rotate(dir * Math.PI / 180);
const arrowBaseY = 3;
context.beginPath();
context.moveTo(-2, arrowBaseY);
context.lineTo(2, arrowBaseY);
context.lineTo(0, 8);
context.closePath();
context.fillStyle = colorScale(dir);
context.fill();
context.beginPath();
context.moveTo(0, arrowBaseY);
context.lineTo(0, -2);
context.strokeStyle = colorScale(dir)
context.stroke();
context.restore();
}
return context.canvas;
}
Insert cell
svgMap = ()=>{
const pathGenerator = d3.geoPath().projection(mProjection);
const svg = createSVG(WIDTH,HEIGHT);
svg.append("rect")
.attr("width",WIDTH).attr("height",HEIGHT).style("fill","black");
svg.append("g").append("path").datum(mLand).attr("d",pathGenerator).style("fill","none").style("stroke","#eee");
svgDrawVectorField(svg,mData.map(d=>{const xy=mProjection([d.longitude,d.latitude]); return {x:xy[0], y:xy[1], dir: d.dir, scale: mAreaScale(d.speed), color: mColorScale(d.dir)};}));
return svg.node();
}
Insert cell
createSVG= function(w,h){
return d3.create("svg")
.attr("width", w)
.attr("height", h)
.style("display","block")
}
Insert cell
import {data as mData, projection as mProjection, land as mLand, scale as mAreaScale, color as mColorScale} from "@d3/vector-field"
Insert cell
import {radio} from "@jashkenas/inputs"
Insert cell
import {usMap, margin} from "@spattana/covid-19-update"
Insert cell
d3 = require("d3@5")
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