Public
Edited
Mar 16
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
coor = [[[-18, -89.999999], [-18, 89.999999], [18, 89.999999], [18, -89.999999], [-18, -89.999999], ]]
Insert cell
hsla10 = [
`hsla(0, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // red
// `hsla(340, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // magentared
`hsla(300, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // magenta
`hsla(280, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // violet
`hsla(240, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // blue
`hsla(200, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // azure
`hsla(180, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // cyan
// `hsla(160, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // cyangreen
`hsla(120, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // green
`hsla(80, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // lime
`hsla(60, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // yellow
`hsla(40, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // orange
`hsla(0, ${s / 10}%, ${l / 10}%, ${a / 10}%)`, // red
]
Insert cell
deczones = [...Array(10).keys()].map(
i => ({
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [coor[0].map(t => [t[0]+36*i, t[1]])]},
"properties": []
})
)
Insert cell
// adapted from https://observablehq.com/@mbostock/autosize-svg
getLabelLength = (label, labelFont = "12px sans-serif") => {
const id = DOM.uid("label").id;
const svg = html`<svg>
<style> .${id} { font: ${labelFont} } </style>
<g id=${id}>
<text class="${id}">${DOM.text(label)}</text>
</g>
</svg>`;

// Add the SVG element to the DOM so we can determine its size.
document.body.appendChild(svg);

// Compute the bounding box of the content.
const width = svg.getElementById(id).getBBox().width;

// Remove the SVG element from the DOM.
document.body.removeChild(svg);

return width;
}
Insert cell
// https://observablehq.com/@bayre/svg-swatches
function swatches({
colour,
swatchRadius = 7.75,
swatchPadding = swatchRadius * (2/3),
labelFont = "12px sans-serif",
labelFormat = x => x,
labelPadding = swatchRadius * 1.5,
marginLeft = 0
} = {}) {
const spacing = colour
.domain()
.map(d => labelFormat(d))
.map(d => getLabelLength(d, labelFont) + (swatchRadius * 2) + swatchPadding + labelPadding)
.map((_, i, g) => d3.cumsum(g)[i] + marginLeft)
const width = d3.max(spacing)
const height = swatchRadius * 2 + swatchPadding * 2
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible")
.style("display", "block");
const g = svg
.append("g")
.attr("transform", `translate(0, ${height / 2})`)
.selectAll("g")
.data(colour.domain())
.join("g")
.attr("transform", (d, i) => `translate(${spacing[i - 1] || marginLeft}, 0)`);
g.append("circle")
.attr("fill", colour)
.attr("stroke", "black")
.attr("r", swatchRadius)
.attr("cx", swatchRadius)
.attr("cy", 0);
g.append("text")
.attr("x", swatchRadius * 2 + swatchPadding)
.attr("y", 0)
.attr("dominant-baseline", "central")
.style("font", labelFont)
.text(d => labelFormat(d));
return svg.node()
}
Insert cell
height = width
Insert cell
projection = d3.geoOrthographic()
.rotate([-sun[0], -sun[1]])
.fitExtent([[1, 1], [width - 1, height - 1]], sphere)
.precision(0.1)
Insert cell
sun = {
const now = new Date;
const day = new Date(+now).setUTCHours(0, 0, 0, 0);
const t = solar.century(now);
const x = (day - now) / 864e5 * 360 - 180 - solar.equationOfTime(t) / 4;
const y = solar.declination(t);
return [x % 360, y];
}
Insert cell
sphere = ({type: "Sphere"})
Insert cell
graticule = d3.geoGraticule().stepMinor([36,36]).stepMajor([36,36])()
Insert cell
TZ0end = -126
Insert cell
graticule.coordinates.forEach((part, index, theArray) => {
if (theArray[index].length === 3) {
theArray[index][0][0] = TZ0end + 36 * index;
theArray[index][1][0] = TZ0end + 36 * index;
theArray[index][2][0] = TZ0end + 36 * index;
}
});
Insert cell
graticule.coordinates
Insert cell
land = topojson.feature(world, world.objects.land)
Insert cell
borders = topojson.mesh(countries, countries.objects.countries, (a, b) => a !== b)
Insert cell
countries = fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json").then(response => response.json())
Insert cell
world = fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/land-50m.json").then(response => response.json())
Insert cell
topojson = require("topojson-client@3")
Insert cell
d3 = require("d3@5", "d3-array@2.4", "d3-geo@1")
Insert cell
solar = require("solar-calculator@0.3/dist/solar-calculator.min.js")
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