Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
D

d3-celestial

> 编程语言
Open source

A star map with d3.js

734 stars0 likes3 views
WebsiteGitHub

About

A star map with d3.js

Celestial map with D3.js

Interactive, adaptable celestial map done with the D3.js visualization library. So, GeoJSON for sky stuff. Which surprisingly nobody has done yet, it seems.

Features display of stars and deep sky objects (DSOs) with a selectable magnitude limit up to 6, or choose different GeoJSON data source for higher magnitudes. Also shows constellations with names, lines and/or boundaries, the Milky Way band and grid lines. Alternate coordinate spaces e.g. ecliptc, galactic or supergalactic are also possible. Full support for zoom and rotation with mouse or gestures.

Since it uses D3.js and HTML5 canvas, it needs a modern browser with canvas support, so any recent flavor of Chrome/Firefox/Safari/Opera or IE 9 and above should suffice. Check out the demo at armchairastronautics.blogspot.com or clone/download it for local usage, which works with Chrome if it is started with command line parameter --allow-file-access-from-files to load local json files. Or use a local web server environment, quite easy to do with node.js.

Demos:
Simple map with editable configuration
Interactive form map viewer with all config options
Wall map for printing
Setting time/location and see the current sky
Animated planets moving about the ecliptic
Starry sky just the stars
Alternative Stars different way to display stars
Summer triangle adding data
Supernova remnants adding point data
Traditional Chinese constellation a different culture altogether
(Source files on github)

Some more examples:
Embedded interactive form
Spinning sky globe
The Milky Way halo, globular clusters & satellite galaxies
The Local Group of galaxies
Asterisms with locations & time selection
Asterisms with zoom & pan
Zoom & pan animations
A different kind of Messier marathon
Show coordinates, DSO colors, Download button
Geolocator gadget part I: Geolocator globe - Part II: Daylight sky - Part III: Geomarker - Part IV: Night sky

Usage

  • On your HTML add a div with some id, e.g.: .

  • Optionally add a div with the id "celestial-form" if you are going to use some of the built-in forms: .

  • Include the d3-celestial script, available as celestial.js or celestial.min.js.

  • Include the necessary d3 scripts: d3.min.js and d3.geo.projection.min.js. Available on the lib subfolder in this repository or from the official d3.js server http://d3js.org/.

  • On your script display the map with Celestial.display(config). Remember to indicate the id of the div where the map will be shown. Check and edit the following default configuration file.

…

js var jsonLine = { "type":"FeatureCollection", // this is an array, add as many objects as you want "features":[ {"type":"Feature", "id":"SummerTriangle", "properties": { // Name "n":"Summer Triangle", // Location of name text on the map "loc": [-67.5, 52] }, "geometry":{ // the line object as an array of point coordinates, // always as [ra -180..180 degrees, dec -90..90 degrees] "type":"MultiLineString", "coordinates":[[ [-80.7653, 38.7837], [-62.3042, 8.8683], [-49.642, 45.2803], [-80.7653, 38.7837] ]] } }
] };


As you can see, this defines the Summer Triangle asterism, consisting of the bright stars Vega (Alpha Lyr), Deneb (Alpha Cyg) and Altair (Alpha Aql).  
*Note:* Since astronomical data is usually given in right ascension from 0 to 24 h and the geoJSON-format used in D3 expects positions in degrees from -180 to 180 deg, you may need this function to convert your data first:  
```js
function hour2degree(ra) { 
  return ra > 12 ? (ra - 24) * 15 : ra * 15;
}

You also need to define how the triangle is going to look like with some styles (see definitions above). The parameters and values usually have the same formats as SVG- or CSS-data:

javascript
var lineStyle = { 
      stroke: "#f00", 
      fill: "rgba(255, 204, 204, 0.4)",
      width: 3 
    };
var textStyle = { 
      fill: "#f00", 
      font: "bold 15px Helvetica, Arial, sans-serif", 
      align: "center", 
      baseline: "bottom" 
    };

Now we can get to work, with the function

Celestial.add({file:string, type:json|raw, callback:function, redraw:function)

The file argument is optional for providing an external geoJSON file; since we already defined our data, we don't need it. Type is 'json' for JSON-Formatted data. That leaves two function definitions, the first one gets called on loading, this is where we add our data to the d3-celestial data container, and redraw is called on every redraw event for the map, this is where you define how to display the added object(s).

javascript
callback: function(error, json) {
  if (error) return console.warn(error);
  // Load the geoJSON file and transform to correct coordinate system, if necessary
  var asterism = Celestial.getData(jsonLine, config.transform);

  // Add to celestial objects container in d3
  Celestial.container.selectAll(".asterisms")
    .data(asterism.features)
    .enter().append("path")
    .attr("class", "ast"); 
  // Trigger redraw to display changes
  Celestial.redraw();
}

The callback funtion is pretty straight forward: Load the data with Celestial.getData, add to Celestial.container in the usual d3 manner, and redraw. It also provides a json parameter that contains the parsed JSON if a file property is given, but we already have defined jsonLine above, so we use that.

javascript
redraw: function() {   
  // Select the added objects by class name as given previously
  Celestial.container.selectAll(".ast").each(function(d) {
    // Set line styles 
    Celestial.setStyle(lineStyle);
    // Project objects on map
    Celestial.map(d);
    // draw on canvas
    Celestial.context.fill();
    Celestial.context.stroke();
    
    // If point is visible (this doesn't work automatically for points)
    if (Celestial.clip(d.properties.loc)) {
      // get point coordinates
      pt = Celestial.mapProjection(d.properties.loc);
      // Set text styles       
      Celestial.setTextStyle(textStyle);
      // and draw text on canvas
      Celestial.context.fillText(d.properties.n, pt[0], pt[1]);
    }      
  })
}

And the redraw function with the actual display of the elements, contained in a d3.selectAll call on the previously set class property of the added objects. Celestial.setStyle applies the predefined canvas styles, Celestial.map projects each line on the map. However, that doesn't work for points, so that is done manually with Celestial.clip (true if point is currently visible) and Celestial.mapProjection. and the rest are standard canvas fill and stroke operations. The beginPath and closePath commands are done automatically.

javascript
Celestial.display();

…

js
var jsonSN = {
  "type":"FeatureCollection",
  // this is an array, add as many objects as you want
  "features":[
    {"type":"Feature",
     "id":"SomeDesignator",
     "properties": {
       // Name
       "name":"Some Name",
       // magnitude, dimension in arcseconds or any other size criterion
       "mag": 10,
       "dim": 30
     }, "geometry":{
       // the location of the object as a [ra, dec] array in degrees [-180..180, -90..90]
       "type":"Point",
       "coordinates": [-80.7653, 38.7837]
     }
    }  
  ]};

Next we define the appearance of the objects and labels as they will appear on the map. The values are equivalent to CSS-formats. Fill and stroke colors are only necessary if the objects should appear solid (fill) or as an outline (stroke), or an outline with a semitransparent filling as below. Width gives the line width for outlines.

javascript
var pointStyle = { 
      stroke: "#f0f", 
      width: 3,
      fill: "rgba(255, 204, 255, 0.4)"
    };
var textStyle = { 
      fill:"#f0f", 
      font: "bold 15px Helvetica, Arial, sans-serif", 
      align: "left", 
      baseline: "bottom" 
    };

Now we are ready to add the functions that do the real work of putting the data on the map.

javascript
Celestial.add({file:string, type:json|raw, callback:function, redraw:function)

…

js
callback: function(error, json) {
  if (error) return console.warn(error);
  // Load the geoJSON file and transform to correct coordinate system, if necessary
  var dsn = Celestial.getData(jsonSN, config.transform);

  // Add to celestial objects container in d3
  Celestial.container.selectAll(".snrs")
    .data(asterism.features)
    .enter().append("path")
    .attr("class", "snr"); 
  // Trigger redraw to display changes
  Celestial.redraw();
}

Or add data from an external file with optional filtering, as shown below. In this case the file parameter of the Celsestial.add() function needs to give a valid url to the data file, while the filter function returns true for every object that meets the intended criteria.

javascript
callback: function(error, json) {
  if (error) return console.warn(error);
  // Load the geoJSON file and transform to correct coordinate system, if necessary
  var dsos = Celestial.getData(json, config.transform);

  // Filter SNRs and add to celestial objects container in d3
  Celestial.container.selectAll(".snrs")
    .data(dsos.features.filter(function(d) {
      return d.properties.type === 'snr'
    }))
    .enter().append("path")
    .attr("class", "snr"); 
  // Trigger redraw to display changes
  Celestial.redraw();
}

…

js
redraw: function() {
  // Select the added objects by class name as given previously
  Celestial.container.selectAll(".snr").each(function(d) {
    // If point is visible (this doesn't work automatically for points)
    if (Celestial.clip(d.geometry.coordinates)) {
      // get point coordinates
      var pt = Celestial.mapProjection(d.geometry.coordinates);
      // object radius in pixel, could be varable depending on e.g. dimension or magnitude 
      var r = Math.pow(20 - prop.mag, 0.7); // replace 20 with dimmest magnitude in the data
   
      // draw on canvas
      //  Set object styles fill color, line color & width etc.
      Celestial.setStyle(pointStyle);
      // Start the drawing path
      Celestial.context.beginPath();
      // Thats a circle in html5 canvas
      Celestial.context.arc(pt[0], pt[1], r, 0, 2 * Math.PI);
      // Finish the drawing pat

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

JavaScriptcanvascelestial-mechanicsd3jsgeojson-data

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言