Published
Edited
May 8, 2022
1 fork
20 stars
Insert cell
# Stars
Insert cell
chart = {
const context = DOM.context2d(width, height);
const path = d3.geoPath(projection, context);
const constellationLinesPath = d3.geoPath(projection, context);
const graticulePath = d3.geoPath(projection, context);
const starPath = d3
.geoPath(projection, context)
.pointRadius((d) => magnitudeScale(d.properties.mag));

function render() {
context.clearRect(0, 0, width, height);

// sphere fill
context.beginPath(),
path(sphere),
(context.fillStyle = "#000"),
context.fill();

// graticule
context.beginPath(),
graticulePath(graticule),
(context.strokeStyle = "#000"),
context.stroke();

// stars
stars.features.forEach((star) => {
context.beginPath(),
starPath(star),
(context.fillStyle = "#999"),
context.fill();
});

// constellation lines
context.beginPath(),
constellationLinesPath(constellationLines),
(context.strokeStyle = "#ffffff"),
context.stroke();

// sphere boundary
context.beginPath(), path(sphere), context.stroke();
}

return d3
.select(context.canvas)
.call(
drag(projection)
.on("drag.render", () => render())
.on("end.render", () => render())
)
.call(() => render())
.node();
}
Insert cell
function drag(projection) {
let v0, q0, r0;

function dragstarted() {
v0 = versor.cartesian(projection.invert([d3.event.x, d3.event.y]));
q0 = versor((r0 = projection.rotate()));
}

function dragged() {
const v1 = versor.cartesian(
projection.rotate(r0).invert([d3.event.x, d3.event.y])
);
const q1 = versor.multiply(q0, versor.delta(v0, v1));
projection.rotate(versor.rotation(q1));
}

return d3.drag().on("start", dragstarted).on("drag", dragged);
}
Insert cell
projection = d3[projectionName]().precision(0.1)
Insert cell
projectionName = "geoOrthographic"
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
magnitudeScale = d3
.scaleLinear()
.domain(d3.extent(stars.features, (d) => d.properties.mag))
.range([5, 1])
Insert cell
graticule = d3.geoGraticule10()
Insert cell
stars = d3.json(
"https://raw.githubusercontent.com/ofrohn/d3-celestial/master/data/stars.6.json"
)
Insert cell
constellationLines = d3.json(
"https://raw.githubusercontent.com/ofrohn/d3-celestial/master/data/constellations.lines.json"
)
Insert cell
sphere = ({ type: "Sphere" })
Insert cell
versor = require("versor@0.0.3")
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