Published
Edited
Dec 8, 2019
Insert cell
Insert cell
Insert cell
md`## switch between auto to manual rotate`
Insert cell
viewof b = button({value: "auto or manual rotate"})
Insert cell
b
Insert cell
autoManual = {
b;
return !this;
}
Insert cell
mutable currentPos = 1;
Insert cell
viewof manualRotate = {
currentPos;
return slider({min:1, max:360, value:currentPos, step: 1, title: "manualRotate"})
}
Insert cell
manualRotate
Insert cell
rotatingGlobe = {
// For every frame.
while (autoManual) { // true or autoManual
// Rotate the earth. For fun, try replacing the `0` in the following line with `canvas.angle`.
projection.rotate([context.canvas.angle = (context.canvas.angle >= 360)? context.canvas.angle - 360 + spinSpeed : context.canvas.angle + spinSpeed, 0]);
context.clearRect(0, 0, w, w); // visually it avoids rough edges of the globe
mutable currentPos = context.canvas.angle;
yield context.canvas.angle; // or true or anything (can be used for inspection)
}
if (!autoManual) {
projection.rotate([manualRotate, 0]);
context.canvas.angle = manualRotate;
}
}

Insert cell
Insert cell
Insert cell
import {slider, color, button} from "@embracelife/tutorial-utilities"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
world = (await fetch("https://unpkg.com/world-atlas@1/world/110m.json")).json()
Insert cell
Insert cell
earth = topojson.feature(world, world.objects[land])
Insert cell
land // see section below
Insert cell
Insert cell
urls = ({
"past-day": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson",
"past-week": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson",
"past-month": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_month.geojson",
"past-month-all": "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson"
})
Insert cell
Insert cell
timeFrame // see section below
Insert cell
quakes = (await fetch(urls[timeFrame])).json()
Insert cell
Insert cell
viewof timeFrame = {
const select = DOM.select(["past-day", "past-week", "past-month", "past-month-all"]);
select.value = "past-week";
return select;
}
Insert cell
viewof dots = DOM.select(["projected", "unprojected"])
Insert cell
viewof land = DOM.select(["countries", "land"])
Insert cell
Insert cell
Insert cell
magnitudeRadius = {
const scale = d3.scaleSqrt().domain([0, 100]).range([0, quakeSize]);
return function(quake) {
return scale((Math.exp(quake.properties.mag)));
}
}
Insert cell
Insert cell
exampleQuakeData = quakes.features[30].properties
Insert cell
exampleQuakeMagnitude = magnitudeRadius({properties: exampleQuakeData})
Insert cell
Insert cell
Insert cell
quakeCircles = {
const circle = d3.geoCircle();
return quakes.features.map(quake => {
return circle
.center(quake.geometry.coordinates) // where the quake is at (geojson)
.radius(magnitudeRadius(quake) / 5) // circle is polygon, smaller the radius, the more like a circle
.precision(25)(); // less precision, more like circle
});
}
Insert cell
// Use an orthographic projection of the world. For fun, try changing `Ortho` to `Stereo`.
projection = d3.geoOrthographic().scale(r).translate([w / 2, w / 2]);
Insert cell
path = d3.geoPath(projection, context);
Insert cell
// create an inspection function
function inspection(name, value){
context.font = "50px";
context.fillStyle = "red";
context.fillText(name + " : " + value, w/2, w/2);
}
Insert cell
quakeColorD3 = {
// color for quakes
const color = d3.color(quakeColor);
color.opacity = quakeOpacity;
return color;
}
Insert cell
Insert cell
draw_oceans = function(oceanColor) {
// Draw the seas onto the canvas
context.lineWidth = 1.5;
context.fillStyle = oceanColor;
context.beginPath();
context.arc(w / 2, w / 2, r, 0, 2 * Math.PI);
context.fill();
context.stroke();
}
Insert cell
function draw_land(landColor) {
context.lineWidth = lineWidth;
context.fillStyle = landColor;
context.beginPath();
path(earth); // use this svgPath of projection onto canvas
context.fill();
context.stroke();
}
Insert cell
draw_quakes = function(quakeColor) {
// Draw the earthquakes, either as projected circles on the surface, or flat circles in space.
context.fillStyle = quakeColor;
let circles = dots == "projected" ? quakeCircles : quakes.features; // use quakeCircles or not
if (dots == "unprojected") path.pointRadius(magnitudeRadius); // not use quakeCircles, set radius
circles.forEach(d => { // circles can be either quakeCircles or just quake.features
context.beginPath();
path(d);
context.fill()
});
path.pointRadius(null); //
}
Insert cell
draw = {
rotatingGlobe; // auto rotation
manualRotate; // manual rotation
// Draw the seas (seas are everywhere)
draw_oceans(oceanColor);

// Draw the land (provided by the topojson)
draw_land(landColor);

draw_quakes(quakeColorD3);

// drawing for inspection
inspection("canvas.angle", context.canvas.angle);

}
Insert cell
Insert cell
viewof lineWidth = slider({min: 0.01, max: 5, value: 0.35, title: "lineWidth", description: "lineWidth for land"})
Insert cell
viewof quakeSize = slider({min: 1, max: 20, value: 10, title: "quakeSize", description: "set max magnitudue"})
Insert cell
viewof padding = slider({min: 1, max: 100, value: 10, title: "padding", description: "add padding to shrink the size of globe, use w and padding to set the globe radius"})
Insert cell
viewof spinSpeed = slider({min: 0, max: 3, value: 0.4, title: "spinSpeed", description: "add spinSpeed in while loop to rotate automatically"})
Insert cell
viewof quakeOpacity = slider({min: 0, max: 1, value: 0.25, title: "quakeOpacity"})
Insert cell
Insert cell
viewof oceanColor = color({value: "#74fbfd", title: "oceanColor"})
Insert cell
viewof landColor = color({value: "#fefafa", title: "landColor"})
Insert cell
viewof quakeColor = color({value: "#f11707", title: "quakeColor"})
Insert cell
Insert cell
Insert cell
Insert cell
w = Math.min(680, width)
Insert cell
r = w / 2 - 2 - padding // use w and padding to set the globe radius
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