Public
Edited
Apr 22, 2024
Insert cell
Insert cell
Insert cell
Insert cell
viewof selectProjection = Inputs.select(availableProjections, {label: "Select Projection", format: x => x.name})
//Inputs.select(["geoNaturalEarth1", "geoCylindricalEqualArea"], {label: "Select a Projection"})
Insert cell
viewof rangeRotationX = Inputs.range([0.000, 0.01], {label: "Rotation Speed", step: 0.001, value: 0.005})
Insert cell
map2 = {
const vx = rangeRotationX, vy = -0.000;
const context = DOM.context2d(width, height);
const path = d3.geoPath(projection, context);
//context.canvas.style.width = selectProjection["width"];
//projection.rotate([70,-20])
const startingX = 0;
const startingY = 0;
const tStart = performance.now();
while (true) {
const t = performance.now() - tStart;
projection.rotate([startingX+(vx * t), startingY + (vy * t)]);
context.save();
context.beginPath();
//projection.precision(0.2);
context.globalAlpha = 1;
//path(graticule);
//context.stroke();
//context.beginPath();
//projection.precision(0);
context.beginPath(), path(graticule), context.strokeStyle = "#ccc", context.stroke();
context.beginPath(), path(land), context.fillStyle = "#000", context.fill();
context.beginPath(), path(borders), context.strokeStyle = "#AAA", context.stroke();
context.beginPath(), path(circles), context.fillStyle = "tomato", context.fill() ;
context.beginPath(), path(night2()), context.fillStyle = "rgba(0,0,255,0.3)", context.fill();
context.beginPath(), path(sphere), context.strokeStyle = "#000", context.stroke();
context.globalAlpha = 0.3;
circles.forEach(element => {
context.beginPath(), path(element()), context.fillStyle = "tomato", context.fill(), context.opacity = 0.2 ;
});
context.globalAlpha = 1;
//context.fill();
//context.beginPath();
context.lineWidth = 1;
//context.arc(width / 2, height / 2, width / 2 - 20, 0, 2 * Math.PI, false);
//context.stroke();
context.restore();
yield context.canvas;
context.clearRect(0, 0, width, height);

}
}
Insert cell
map3 = {
//const vx = rangeRotationX, vy = -0.000;
const context = DOM.context2d(width, height);
const path = d3.geoPath(projection2, context);
//context.canvas.style.width = selectProjection["width"];
//projection2.rotate([70,-20])
const startingX = 0;
const startingY = 0;
const tStart = performance.now();
var diff = 0
while (true) {
//const t = tStart.setUTCHours(0, 0, 0, 0);
const tod = tStart + diff*60000;
diff = diff+10;
//projection.rotate([startingX+(vx * t), startingY + (vy * t)]);
context.save();
context.beginPath();
//projection.precision(0.2);
context.globalAlpha = 1;
//path(graticule);
//context.stroke();
//context.beginPath();
//projection.precision(0);
context.beginPath(), path(graticule), context.strokeStyle = "#ccc", context.stroke();
context.beginPath(), path(land), context.fillStyle = "#000", context.fill();
context.beginPath(), path(borders), context.strokeStyle = "#AAA", context.stroke();
context.beginPath(), path(circles), context.fillStyle = "tomato", context.fill() ;
context.beginPath(), path(night3(tod)), context.fillStyle = "rgba(0,0,255,0.3)", context.fill();
context.beginPath(), path(sphere), context.strokeStyle = "#000", context.stroke();
context.globalAlpha = 0.3;
circles.forEach(element => {
context.beginPath(), path(element()), context.fillStyle = "tomato", context.fill(), context.opacity = 0.2 ;
});
context.globalAlpha = 1;
//context.fill();
//context.beginPath();
context.lineWidth = 1;
//context.arc(width / 2, height / 2, width / 2 - 20, 0, 2 * Math.PI, false);
//context.stroke();
context.restore();
yield context.canvas;
context.clearRect(0, 0, width, height);

}
}
Insert cell
map = {

const context = DOM.context2d(width, height);
const path = d3.geoPath(projection, context);
//const canvas = context.canvas;
//context.canvas.style.width = selectProjection["width"];
context.beginPath(), path(graticule), context.strokeStyle = "#ccc", context.stroke();
context.beginPath(), path(land), context.fillStyle = "#000", context.fill();
context.beginPath(), path(borders), context.strokeStyle = "#555", context.stroke();
context.beginPath(), path(night), context.fillStyle = "rgba(0,0,255,0.3)", context.fill();
context.beginPath(), path(sphere), context.strokeStyle = "#000", context.stroke();
context.globalAlpha = 0.3;
circles.forEach(element => {
context.beginPath(), path(element()), context.fillStyle = "tomato", context.fill() ;
});

//projection.postclip([-22.6072, 63.7731, 4.486, -22.1579, 64.0848, 11.878]);
return context.canvas;
}
Insert cell
width = 1080 * (parseFloat(selectProjection["width"]) / 100);
Insert cell
height = {
const [[x0, y0], [x1, y1]] = d3.geoPath(projection.fitWidth(width, sphere)).bounds(sphere);
const dy = Math.ceil(y1 - y0), l = Math.min(Math.ceil(x1 - x0), dy);
projection.scale(projection.scale() * (l - 1) / l).precision(0.2);
return dy;
}
Insert cell
height2 = {
const [[x0, y0], [x1, y1]] = d3.geoPath(projection2.fitWidth(width, sphere)).bounds(sphere);
const dy = Math.ceil(y1 - y0), l = Math.min(Math.ceil(x1 - x0), dy);
projection2.scale(projection2.scale() * (l - 1) / l).precision(0.2);
return dy;
}
Insert cell
projection = selectProjection["value"]();
Insert cell
projection2 = selectProjection["value"]();
Insert cell
sun = {
const now = new Date;
const day = new Date(+now).setUTCHours(0, 0, 0, 0);
const t = solar.century(now);
const longitude = (day - now) / 864e5 * 360 - 180;
return [longitude - solar.equationOfTime(t) / 4, solar.declination(t)];
}
Insert cell
function sun2() {
const now = new Date;
const day = new Date(+now).setUTCHours(0, 0, 0, 0);
const t = solar.century(now);
const longitude = (day - now) / 864e5 * 360 - 180;
return [longitude - solar.equationOfTime(t) / 4, solar.declination(t)];
}

Insert cell
function sun3(tod) {
//const now = new Date;
const day = new Date(+tod).setUTCHours(0, 0, 0, 0);
const t = solar.century(tod);
const longitude = (day - tod) / 864e5 * 360 - 180;
return [longitude - solar.equationOfTime(t) / 4, solar.declination(t)];
}

Insert cell
night = d3.geoCircle()
.radius(90)
.center(antipode(sun2()))
()
Insert cell
function night2() {
return d3.geoCircle()
.radius(90)
.center(antipode(sun2()))
()
}
Insert cell
function night3(tod) {
return d3.geoCircle()
.radius(90)
.center(antipode(sun3(tod)))
()
}
Insert cell
antipode = ([longitude, latitude]) => [longitude + 180, -latitude]
Insert cell
sphere = ({type: "Sphere"})
Insert cell
graticule = d3.geoGraticule10()
Insert cell
land = topojson.feature(world, world.objects.land)
Insert cell
countries = topojson.feature(world, world.objects.countries)
Insert cell
borders = topojson.mesh(world, world.objects.countries, (a, b) => a !== b)
Insert cell
//world = fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/land-50m.json").then(response => response.json())
world = fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json").then(response => response.json())
Insert cell
//Countries = fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json").then(response => response.json())
Insert cell
topojson = require("topojson-client@3")
Insert cell
circles = earthquakes.map(d => d3.geoCircle()
.center([d.longitude, d.latitude])
.radius((d.magnitude*25) / (6371 * Math.PI * 2) * 360)
//.radius(600 / (6371 * Math.PI * 2) * 360)
.precision(1)
);
Insert cell
d3 = require("d3-geo@3", "d3-geo-projection@4")
Insert cell
solar = require("solar-calculator@0.3/dist/solar-calculator.min.js")
Insert cell
earthquakes = fetch("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.geojson").then(response => response.json()).then(d => d.features.map(f => {
const c = d3.geoCentroid(f);
return {magnitude: f.properties.mag, longitude: c[0], latitude: c[1]};
}))
Insert cell
iceland_snap = FileAttachment("Iceland_snapshot.json").json()
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