{"id":13583629,"url":"https://github.com/ofrohn/d3-celestial","last_synced_at":"2025-04-06T21:32:46.057Z","repository":{"id":25666296,"uuid":"29102054","full_name":"ofrohn/d3-celestial","owner":"ofrohn","description":"A star map with d3.js","archived":false,"fork":false,"pushed_at":"2024-08-12T13:13:10.000Z","size":199144,"stargazers_count":659,"open_issues_count":44,"forks_count":184,"subscribers_count":29,"default_branch":"master","last_synced_at":"2025-03-26T03:34:28.919Z","etag":null,"topics":["canvas","celestial-mechanics","d3js","geojson-data","nightsky","starmap"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ofrohn.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-01-11T18:55:44.000Z","updated_at":"2025-03-20T13:30:09.000Z","dependencies_parsed_at":"2022-07-10T13:00:22.502Z","dependency_job_id":"2fe52756-3a97-46ed-a6fb-7bb0c3c06d55","html_url":"https://github.com/ofrohn/d3-celestial","commit_stats":{"total_commits":486,"total_committers":12,"mean_commits":40.5,"dds":"0.45679012345679015","last_synced_commit":"7e720a3de062059d4c5400a379146a601d9010e0"},"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ofrohn%2Fd3-celestial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ofrohn%2Fd3-celestial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ofrohn%2Fd3-celestial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ofrohn%2Fd3-celestial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ofrohn","download_url":"https://codeload.github.com/ofrohn/d3-celestial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247405834,"owners_count":20933791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["canvas","celestial-mechanics","d3js","geojson-data","nightsky","starmap"],"created_at":"2024-08-01T15:03:39.533Z","updated_at":"2025-04-06T21:32:44.343Z","avatar_url":"https://github.com/ofrohn.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Celestial map with D3.js\n\nInteractive, adaptable celestial map done with the [D3.js](http://d3js.org/) visualization library. So, GeoJSON for sky stuff. Which surprisingly nobody has done yet, it seems.  \n\nFeatures 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.\n\nSince 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 \u003ca href=\"http://armchairastronautics.blogspot.com/p/skymap.html\"\u003earmchairastronautics.blogspot.com\u003c/a\u003e 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.\n\n__Demos__:  \n[Simple map](https://ofrohn.github.io/celestial-demo/map.html) with editable configuration  \n[Interactive form](https://ofrohn.github.io/celestial-demo/viewer.html) map viewer with all config options  \n[Wall map](https://ofrohn.github.io/celestial-demo/wallmap.html) for printing  \n[Setting time/location](https://ofrohn.github.io/celestial-demo/location.html) and see the current sky  \n[Animated planets](https://ofrohn.github.io/celestial-demo/planets-animation.html) moving about the ecliptic  \n[Starry sky](https://ofrohn.github.io/celestial-demo/sky.html) just the stars  \n[Alternative Stars](https://ofrohn.github.io/celestial-demo/altstars.html) different way to display stars  \n[Summer triangle](https://ofrohn.github.io/celestial-demo/triangle.html) adding data  \n[Supernova remnants](https://ofrohn.github.io/celestial-demo/snr.html) adding point data  \n[Traditional Chinese constellation](https://ofrohn.github.io/celestial-demo/chinese.html) a different culture altogether    \n\\([Source files on github](./demo/)\\)  \n\n__Some more examples__:  \n[Embedded interactive form](https://armchairastronautics.blogspot.com/p/skymap.html)  \n[Spinning sky globe](https://armchairastronautics.blogspot.com/2016/04/interactive-skymap-version-05.html)  \n[The Milky Way halo, globular clusters \u0026 satellite galaxies](https://armchairastronautics.blogspot.com/p/milky-way-halo.html)  \n[The Local Group of galaxies](https://armchairastronautics.blogspot.com/p/local-group.html)  \n[Asterisms with locations \u0026 time selection](https://armchairastronautics.blogspot.com/p/asterisms.html)  \n[Asterisms with zoom \u0026 pan](https://armchairastronautics.blogspot.com/2016/05/asterisms-interactive-and-with.html)  \n[Zoom \u0026 pan animations](https://armchairastronautics.blogspot.com/2016/06/and-here-is-d3-celestial-057-with.html)  \n[A different kind of Messier marathon](https://armchairastronautics.blogspot.com/2016/07/a-different-kind-of-messier-marathon.html)  \n[Show coordinates, DSO colors, Download button](https://armchairastronautics.blogspot.com/2019/08/d3-celestial-showboating_25.html)  \n[Geolocator gadget part I: Geolocator globe](https://armchairastronautics.blogspot.com/2019/11/d3-celestial-geolocator.html) - [Part II: Daylight sky](https://armchairastronautics.blogspot.com/2019/12/d3-celestial-sky-color.html) - [Part III: Geomarker](https://armchairastronautics.blogspot.com/2019/12/d3-celestial-geomarker.html) - [Part IV: Night sky](http://armchairastronautics.blogspot.com/2020/01/d3-celestial-gelolocator-night-sky.html)\n\n\n### Usage\n\n* On your HTML add a div with some id, e.g.: `\u003cdiv id=\"celestial-map\"\u003e\u003c/div\u003e`.\n\n* Optionally add a div with the id \"celestial-form\" if you are going to use some of the built-in forms: `\u003cdiv id=\"celestial-form\"\u003e\u003c/div\u003e`.\n\n* Include the d3-celestial script, available as `celestial.js` or `celestial.min.js`.\n\n* 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/`.\n\n* 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.\n\n```js\nvar config = { \n  width: 0,           // Default width, 0 = full parent element width; \n                      // height is determined by projection\n  projection: \"aitoff\",    // Map projection used: see below\n  projectionRatio: null,   // Optional override for default projection ratio\n  transform: \"equatorial\", // Coordinate transformation: equatorial (default),\n                           // ecliptic, galactic, supergalactic\n  center: null,       // Initial center coordinates in set transform\n                      // [longitude, latitude, orientation] all in degrees \n                      // null = default center [0,0,0]\n  orientationfixed: true,  // Keep orientation angle the same as center[2]\n  geopos: null,       // optional initial geographic position [lat,lon] in degrees, \n                      // overrides center\n  follow: \"zenith\",   // on which coordinates to center the map, default: zenith, if location enabled, \n                      // otherwise center\n  zoomlevel: null,    // initial zoom level 0...zoomextend; 0|null = default, 1 = 100%, 0 \u003c x \u003c= zoomextend\n  zoomextend: 10,     // maximum zoom level\n  adaptable: true,    // Sizes are increased with higher zoom-levels\n  interactive: true,  // Enable zooming and rotation with mousewheel and dragging\n  form: true,         // Display form for interactive settings. Needs a div with\n                      // id=\"celestial-form\", created automatically if not present\n  location: false,    // Display location settings. Deprecated, use formFields below\n  formFields: {\"location\": true,  // Set visiblity for each group of fields with the respective id\n               \"general\": true,  \n               \"stars\": true,  \n               \"dsos\": true,  \n               \"constellations\": true,  \n               \"lines\": true,  \n               \"other\": true,  \n               \"download\": false},  \n  advanced: true,     // Display fewer form fields if false \n  daterange: [],      // Calender date range; null: displaydate-+10; [n\u003c100]: displaydate-+n; [yr]: yr-+10; \n                      // [yr, n\u003c100]: [yr-n, yr+n]; [yr0, yr1]  \n  controls: true,     // Display zoom controls\n  lang: \"\",           // Global language override for names, any name setting that has the chosen language available\n                      // Default: desig or empty string for designations, other languages as used anywhere else\n  culture: \"\",        // Source of constellations and star names, default \"iau\", other: \"cn\" Traditional Chinese\n  container: \"map\",   // ID of parent element, e.g. div, null = html-body\n  datapath: \"data/\",  // Path/URL to data files, empty = subfolder 'data'\n  stars: {\n    show: true,    // Show stars\n    limit: 6,      // Show only stars brighter than limit magnitude\n    colors: true,  // Show stars in spectral colors, if not use default color\n    style: { fill: \"#ffffff\", opacity: 1 }, // Default style for stars\n    designation: true, // Show star names (Bayer, Flamsteed, Variable star, Gliese or designation, \n                       // i.e. whichever of the previous applies first); may vary with culture setting\n    designationType: \"desig\",  // Which kind of name is displayed as designation (fieldname in starnames.json)\n    designationStyle: { fill: \"#ddddbb\", font: \"11px 'Palatino Linotype', Georgia, Times, 'Times Roman', serif\", align: \"left\", baseline: \"top\" },\n    designationLimit: 2.5,  // Show only names for stars brighter than nameLimit\n    propername: false,   // Show proper name (if present)\n    propernameType: \"name\", // Languge for proper name, default IAU name; may vary with culture setting \n                            // (see list below of languages codes available for stars)\n    propernameStyle: { fill: \"#ddddbb\", font: \"13px 'Palatino Linotype', Georgia, Times, 'Times Roman', serif\", align: \"right\", baseline: \"bottom\" },\n    propernameLimit: 1.5,  // Show proper names for stars brighter than propernameLimit\n    size: 7,       // Maximum size (radius) of star circle in pixels\n    exponent: -0.28, // Scale exponent for star size, larger = more linear\n    data: 'stars.6.json' // Data source for stellar data, \n                         // number indicates limit magnitude\n  },\n  dsos: {\n    show: true,    // Show Deep Space Objects \n    limit: 6,      // Show only DSOs brighter than limit magnitude\n    colors: true,  // // Show DSOs in symbol colors if true, use style setting below if false\n    style: { fill: \"#cccccc\", stroke: \"#cccccc\", width: 2, opacity: 1 }, // Default style for dsos\n    names: true,   // Show DSO names\n    namesType: \"name\",  // Type of DSO ('desig' or language) name shown\n                        // (see list below for languages codes available for dsos)\n    nameStyle: { fill: \"#cccccc\", font: \"11px Helvetica, Arial, serif\", \n                 align: \"left\", baseline: \"top\" }, // Style for DSO names\n    nameLimit: 6,  // Show only names for DSOs brighter than namelimit\n    size: null,    // Optional seperate scale size for DSOs, null = stars.size\n    exponent: 1.4, // Scale exponent for DSO size, larger = more non-linear\n    data: 'dsos.bright.json', // Data source for DSOs, \n                              // opt. number indicates limit magnitude\n    symbols: {  //DSO symbol styles, 'stroke'-parameter present = outline\n      gg: {shape: \"circle\", fill: \"#ff0000\"},          // Galaxy cluster\n      g:  {shape: \"ellipse\", fill: \"#ff0000\"},         // Generic galaxy\n      s:  {shape: \"ellipse\", fill: \"#ff0000\"},         // Spiral galaxy\n      s0: {shape: \"ellipse\", fill: \"#ff0000\"},         // Lenticular galaxy\n      sd: {shape: \"ellipse\", fill: \"#ff0000\"},         // Dwarf galaxy\n      e:  {shape: \"ellipse\", fill: \"#ff0000\"},         // Elliptical galaxy\n      i:  {shape: \"ellipse\", fill: \"#ff0000\"},         // Irregular galaxy\n      oc: {shape: \"circle\", fill: \"#ffcc00\", \n           stroke: \"#ffcc00\", width: 1.5},             // Open cluster\n      gc: {shape: \"circle\", fill: \"#ff9900\"},          // Globular cluster\n      en: {shape: \"square\", fill: \"#ff00cc\"},          // Emission nebula\n      bn: {shape: \"square\", fill: \"#ff00cc\", \n           stroke: \"#ff00cc\", width: 2},               // Generic bright nebula\n      sfr:{shape: \"square\", fill: \"#cc00ff\", \n           stroke: \"#cc00ff\", width: 2},               // Star forming region\n      rn: {shape: \"square\", fill: \"#00ooff\"},          // Reflection nebula\n      pn: {shape: \"diamond\", fill: \"#00cccc\"},         // Planetary nebula \n      snr:{shape: \"diamond\", fill: \"#ff00cc\"},         // Supernova remnant\n      dn: {shape: \"square\", fill: \"#999999\", \n           stroke: \"#999999\", width: 2},               // Dark nebula grey\n      pos:{shape: \"marker\", fill: \"#cccccc\", \n           stroke: \"#cccccc\", width: 1.5}              // Generic marker\n    }\n  },\n  planets: {  //Show planet locations, if date-time is set\n    show: false,\n    // List of all objects to show\n    which: [\"sol\", \"mer\", \"ven\", \"ter\", \"lun\", \"mar\", \"jup\", \"sat\", \"ura\", \"nep\"],\n    // Font styles for planetary symbols\n    symbols: {  // Character and color for each symbol in 'which' above (simple circle: \\u25cf), optional size override for Sun \u0026 Moon\n      \"sol\": {symbol: \"\\u2609\", letter:\"Su\", fill: \"#ffff00\", size:\"\"},\n      \"mer\": {symbol: \"\\u263f\", letter:\"Me\", fill: \"#cccccc\"},\n      \"ven\": {symbol: \"\\u2640\", letter:\"V\", fill: \"#eeeecc\"},\n      \"ter\": {symbol: \"\\u2295\", letter:\"T\", fill: \"#00ccff\"},\n      \"lun\": {symbol: \"\\u25cf\", letter:\"L\", fill: \"#ffffff\", size:\"\"}, // overridden by generated crecent, except letter \u0026 size\n      \"mar\": {symbol: \"\\u2642\", letter:\"Ma\", fill: \"#ff6600\"},\n      \"cer\": {symbol: \"\\u26b3\", letter:\"C\", fill: \"#cccccc\"},\n      \"ves\": {symbol: \"\\u26b6\", letter:\"Ma\", fill: \"#cccccc\"},\n      \"jup\": {symbol: \"\\u2643\", letter:\"J\", fill: \"#ffaa33\"},\n      \"sat\": {symbol: \"\\u2644\", letter:\"Sa\", fill: \"#ffdd66\"},\n      \"ura\": {symbol: \"\\u2645\", letter:\"U\", fill: \"#66ccff\"},\n      \"nep\": {symbol: \"\\u2646\", letter:\"N\", fill: \"#6666ff\"},\n      \"plu\": {symbol: \"\\u2647\", letter:\"P\", fill: \"#aaaaaa\"},\n      \"eri\": {symbol: \"\\u26aa\", letter:\"E\", fill: \"#eeeeee\"}\n    },\n    symbolStyle: { fill: \"#00ccff\", font: \"bold 17px 'Lucida Sans Unicode', Consolas, sans-serif\", \n             align: \"center\", baseline: \"middle\" },\n    symbolType: \"symbol\",  // Type of planet symbol: 'symbol' graphic planet sign, 'disk' filled circle scaled by magnitude\n                           // 'letter': 1 or 2 letters S Me V L Ma J S U N     \n    names: false,          // Show name in nameType language next to symbol\n    nameStyle: { fill: \"#00ccff\", font: \"14px 'Lucida Sans Unicode', Consolas, sans-serif\", align: \"right\", baseline: \"top\" },\n    namesType: \"desig\"     // Language of planet name (see list below of language codes available for planets), \n                           // or desig = 3-letter designation\n  },\n  constellations: {\n    names: true,      // Show constellation names \n    namesType: \"iau\", // Type of name Latin (iau, default), 3 letter designation (desig) or other language (see list below)\n    nameStyle: { fill:\"#cccc99\", align: \"center\", baseline: \"middle\", \n                 font: [\"14px Helvetica, Arial, sans-serif\",  // Style for constellations\n                        \"12px Helvetica, Arial, sans-serif\",  // Different fonts for diff.\n                        \"11px Helvetica, Arial, sans-serif\"]},// ranked constellations\n    lines: true,   // Show constellation lines, style below\n    lineStyle: { stroke: \"#cccccc\", width: 1, opacity: 0.6 }, \n    bounds: false, // Show constellation boundaries, style below\n    boundStyle: { stroke: \"#cccc00\", width: 0.5, opacity: 0.8, dash: [2, 4] }\n  },  \n  mw: {\n    show: true,     // Show Milky Way as filled multi-polygon outlines \n    style: { fill: \"#ffffff\", opacity: 0.15 }  // Style for MW layers\n  },\n  lines: {  // Display \u0026 styles for graticule \u0026 some planes\n    graticule: { show: true, stroke: \"#cccccc\", width: 0.6, opacity: 0.8,   \n      // grid values: \"outline\", \"center\", or [lat,...] specific position\n      lon: {pos: [\"\"], fill: \"#eee\", font: \"10px Helvetica, Arial, sans-serif\"}, \n      // grid values: \"outline\", \"center\", or [lon,...] specific position\n      lat: {pos: [\"\"], fill: \"#eee\", font: \"10px Helvetica, Arial, sans-serif\"}},    \n    equatorial: { show: true, stroke: \"#aaaaaa\", width: 1.3, opacity: 0.7 },  \n    ecliptic: { show: true, stroke: \"#66cc66\", width: 1.3, opacity: 0.7 },     \n    galactic: { show: false, stroke: \"#cc6666\", width: 1.3, opacity: 0.7 },    \n    supergalactic: { show: false, stroke: \"#cc66cc\", width: 1.3, opacity: 0.7 }\n  },\n  background: {        // Background style\n    fill: \"#000000\",   // Area fill\n    opacity: 1, \n    stroke: \"#000000\", // Outline\n    width: 1.5\n  }, \n  horizon: {  //Show horizon marker, if location is set and map projection is all-sky\n    show: false, \n    stroke: \"#cccccc\", // Line\n    width: 1.0, \n    fill: \"#000000\",   // Area below horizon\n    opacity: 0.5\n  },  \n  daylight: {  //Show day sky as a gradient, if location is set and map projection is hemispheric\n    show: false\n  }\n};\n\n// Display map with the configuration above or any subset thereof\nCelestial.display(config);\n```\n\n__Supported projections:__ Airy, Aitoff, Armadillo, August, Azimuthal Equal Area, Azimuthal Equidistant, Baker, Berghaus, Boggs, Bonne, Bromley, Cassini, Collignon, Craig, Craster, Cylindrical Equal Area, Cylindrical Stereographic, Eckert 1, Eckert 2, Eckert 3, Eckert 4, Eckert 5, Eckert 6, Eisenlohr, Equirectangular, Fahey, Foucaut, Ginzburg 4, Ginzburg 5, Ginzburg 6, Ginzburg 8, Ginzburg 9, Hammer, Hatano, HEALPix, Hill, Homolosine, Kavrayskiy 7, Lagrange, l'Arrivee, Laskowski, Loximuthal, Mercator, Miller, Mollweide, Flat Polar Parabolic, Flat Polar Quartic, Flat Polar Sinusoidal, Natural Earth, Nell Hammer, Orthographic, Patterson, Polyconic, Rectangular Polyconic, Robinson, Sinusoidal, Stereographic, Times, 2 Point Equidistant, van der Grinten, van der Grinten 2, van der Grinten 3, van der Grinten 4, Wagner 4, Wagner 6, Wagner 7, Wiechel and Winkel Tripel. Most of these need the extension [d3.geo.projections](https://github.com/d3/d3-geo-projection/)  \n\n__Supported languages for constellation, star and planet name display:__  (name) Official IAU name, (desig) 3-Letter-Designation, (la) Latin, (en) English, (ar) Arabic,  (zh) Chinese, (cz) Czech, (ee) Estonian, (fi) Finnish, (fr) French, (de) German, (el) Greek, (he) Hebrew, (it) Italian, (ja) Japanese, (ko) Korean, (hi) Hindi, (fa) Persian, (ru) Russian, (es) Spanish, (tr) Turkish  \n\n\n__Style settings__   \n`fill`: fill color [(css color value)](https://developer.mozilla.org/en-US/docs/Web/CSS/color)  \n`opacity`: opacity (number 0..1)  \n_Line styles_  \n`stroke`: outline color [(css color value)](https://developer.mozilla.org/en-US/docs/Web/CSS/color)    \n`width`: line width in pixels (number 0..)  \n`dash`: line dash ([line length, gap length])  \n_Text styles_  \n`font`: well, the font [(css font property)](https://developer.mozilla.org/en-US/docs/Web/CSS/font)  \n`align`: horizontal align (left|center|right|start|end)  \n`baseline`: vertical align (alphabetic|top|hanging|middle|ideographic|bottom)  \n_Symbol style_  \n`shape`: symbol shape (circle|square|diamond|ellipse|marker or whatever else is defined in canvas.js)  \n`symbol`: unicode charcter to represent solar system object.\n\n### Getting Info\n\n__Exposed functions \u0026 objects__ \n* `Celestial.metrics()`  \n   Return object literal with current map dimensions in pixels\n   {width, height, margin, scale}\n\n### Adding Data\n\n__Exposed functions \u0026 objects__  \n* `Celestial.add({file:string, type:json|raw, callback:function, redraw:function, save: function)`  \n   Add data in json-format (json) or directly (raw) to the display  \n   The redraw function is added to the internal call stack of the main display routine  \n   _file_: complete url/path to json data file (type:json)  \n   _type_: type of data being added  \n   _callback_: callback function to call when json is loaded (json)  \n               or to directly add elements to the path (raw)  \n   _redraw_: for interactive display, callback when view changes (optional)  \n   _save_:   for display svg-style, callback when saving as svg (optional)  \n\n* `Celestial.clear()`  \n   Deletes all previously added functions from the display call stack  \n   \n* `Celestial.getData(geojson, transform)`  \n   Function to convert geojson coordinates to transformation  \n   (equatorial, ecliptic, galactic, supergalactic)  \n   Returns geojson-object with transformed coordinates  \n   \n* `Celestial.getPoint(coordinates, transform)`  \n   Function to convert a single coordinate to transformation  \n   (equatorial, ecliptic, galactic, supergalactic)  \n   Returns transformed coordinates  \n\n* `Celestial.getPlanet(id, date)`  \n   Function to get solar system object specified with id  \n   (available ids in config.planets.which array)  \n   Returns planet object with coordinates at specified date \n   \n* `Celestial.container`  \n   The object to add data to in the callback. See D3.js documentation  \n\n* `Celestial.context` \n   The HTML5-canvas context object to draw on in the callback. Also see D3.js documentation  \n  \n* `Celestial.map`  \n   The d3.geo.path object to apply projection to data. Also see D3.js documentation  \n  \n* `Celestial.mapProjection`  \n   The projection object for access to its properties and functions. Also D3.js documentation  \n\n* `Celestial.clip(coordinates)`  \n   Function to check if the object is visible, and set its visiblility  \n   _coordinates_: object coordinates in radians, normally supplied by D3 as geometry.coordinates array  \n\n* `Celestial.setStyle(\u003cstyle object\u003e)`  \n* `Celestial.setTextStyle(\u003cstyle object\u003e)`  \n   Set the canvas styles as documented above under __style settings__. Seperate functions for graphic/text  \n   _\u0026lt;style object\u003e_: object literal listing all styles to set  \n\n* `Celestial.Canvas.symbol()`  \n   Draw symbol shapes directly on canvas context: circle, square, diamond, triangle, ellipse, marker,  \n   stroke-circle, cross-circle\n\n\n### Adding Behaviour\n  \n* `Celestial.addCallback(func)`  \n   Add a callback function that is executed every time the map is redrawn.\n   func: function that is execured in the client context \n     \n### Manipulating the Map\n\n__Exposed functions__  \n\n* `Celestial.rotate({center:[long,lat,orient]})`  \n   Turn the map to the given _center_ coordinates, without parameter returns the current center\n\n* `Celestial.zoomBy(factor)`  \n   Zoom the map by the given _factor_ - \u0026lt; 1 zooms out, \u003e 1 zooms in, without parameter returns the \n   current zoom level\n\n* `Celestial.apply(config)`  \n   Apply configuration changes without reloading the complete map. Any parameter of the above \n   _config_-object can be set except width, projection, transform, and \\*.data, which need a reload\n   and interactive, form, controls, container, which control page structure \u0026 behaviour and should\n   only be set on the initial load.\n   \n* `Celestial.resize({width:px|0|null}|number)`  \n   Change the overall size of the map, canvas object needs a complete reload\n   Optional {_width_: number} or _number_: new size in pixels, or 0 = full parent width\n\n* `Celestial.redraw()`  \n   Just redraw the whole map. \n\n* `Celestial.reload(config)`  \n   Load all the data and redraw the whole map.  \n   Optional _config_: change any configuration parameter before reloading  \n\n* `Celestial.reproject({projection:\u003csee above\u003e})`  \n   Change the map projection.  \n   _projection_: new projection to set  \n\n* `Celestial.date(\u003cdate object\u003e, timezone)`  \n   Change the set date, return current date w/o parameter.  \n   _date_: javascript date-object  \n   _timezone_: offset from UTC in minutes (optional)  \n  \n* `Celestial.location([lat, lon])`  \n   Change the current geolocation and set the time zone automatically, \n   called w/o parameter returns current location  \n   _location_: [latitude, longitude] array in degrees  \n\n* `Celestial.skyview({date:\u003cdate object\u003e, location:[lat, lon], timezone: offset})`  \n   Show the current celestial view for one specific date and/or location,  \n   independent of form fields, all parameters are optional  \n   if location and no time zone is given, sets time zone automatically\n   called w/o parameter returns {date, location, timezone} in same format.  \n   _date_: javascript date-object  \n   _location_: [latitude, longitude] array in degrees  \n   _timezone_: offset from UTC in minutes  \n\n* `Celestial.showConstellation(id)`  \n   Zoom in and focus on the constellaion given by id.  \n   id: string with valid IAU 3-letter constellation identifier, case-insensitive  \n\n### Animations  \n\n__Exposed functions__  \n\n* `Celestial.animate(anims, dorepeat)`  \n  Set the anmation sequence and start it.  \n  _anims_: sequence data (see below)  \n  _dorepeat_: repeat sequence in endless loop  \n  \n* `Celestial.stop(wipe)`  \n  Stop the animation after the current step finishes.  \n  _wipe_: if true, delete the list of animation steps as well  \n\n* `Celestial.go(index)`  \n  Continue the animation, if animation steps set.  \n  _index_: if given, continue at step #index in the anims arrray,  \n  if not, continue where the animation was stopped  \n\n  \n__Animation sequence format:__  \n [  \n {_param_: Animated parameter projection|center|zoom  \n   _value_: Adequate value for each parameter  \n   _duration_: in milliseconds, 0 = exact length of transition  \n   _callback_: optional callback function called at the end of the transition   \n }, ...]   \n\n### HowTo\n\n__1. Add your own data__\n\nFirst of all, whatever you add needs to be valid geoJSON. The various types of objects are described in the readme of the [data folder](./data/). This can be a separate file or a JSON object filled at runtime or defined inline. Like so:  \n\n```js\nvar jsonLine = {\n  \"type\":\"FeatureCollection\",\n  // this is an array, add as many objects as you want\n  \"features\":[\n    {\"type\":\"Feature\",\n     \"id\":\"SummerTriangle\",\n     \"properties\": {\n       // Name\n       \"n\":\"Summer Triangle\",\n       // Location of name text on the map\n       \"loc\": [-67.5, 52]\n     }, \"geometry\":{\n       // the line object as an array of point coordinates, \n       // always as [ra -180..180 degrees, dec -90..90 degrees]\n       \"type\":\"MultiLineString\",\n       \"coordinates\":[[\n         [-80.7653, 38.7837],\n         [-62.3042, 8.8683],\n         [-49.642, 45.2803],\n         [-80.7653, 38.7837]\n       ]]\n     }\n    }  \n  ]\n}; \n```\n\nAs you can see, this defines the Summer Triangle asterism, consisting of the bright stars Vega (Alpha Lyr), Deneb (Alpha Cyg) and Altair (Alpha Aql).  \n*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:  \n```js\nfunction hour2degree(ra) { \n  return ra \u003e 12 ? (ra - 24) * 15 : ra * 15;\n}\n```  \n\nYou 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:  \n\n```js\nvar lineStyle = { \n      stroke: \"#f00\", \n      fill: \"rgba(255, 204, 204, 0.4)\",\n      width: 3 \n    };\nvar textStyle = { \n      fill: \"#f00\", \n      font: \"bold 15px Helvetica, Arial, sans-serif\", \n      align: \"center\", \n      baseline: \"bottom\" \n    };\n```\n\nNow we can get to work, with the function\n\n`Celestial.add({file:string, type:json|raw, callback:function, redraw:function)`\n\nThe 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).  \n\n```js\ncallback: function(error, json) {\n  if (error) return console.warn(error);\n  // Load the geoJSON file and transform to correct coordinate system, if necessary\n  var asterism = Celestial.getData(jsonLine, config.transform);\n\n  // Add to celestial objects container in d3\n  Celestial.container.selectAll(\".asterisms\")\n    .data(asterism.features)\n    .enter().append(\"path\")\n    .attr(\"class\", \"ast\"); \n  // Trigger redraw to display changes\n  Celestial.redraw();\n}\n```\n\nThe 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.\n\n```js\nredraw: function() {   \n  // Select the added objects by class name as given previously\n  Celestial.container.selectAll(\".ast\").each(function(d) {\n    // Set line styles \n    Celestial.setStyle(lineStyle);\n    // Project objects on map\n    Celestial.map(d);\n    // draw on canvas\n    Celestial.context.fill();\n    Celestial.context.stroke();\n    \n    // If point is visible (this doesn't work automatically for points)\n    if (Celestial.clip(d.properties.loc)) {\n      // get point coordinates\n      pt = Celestial.mapProjection(d.properties.loc);\n      // Set text styles       \n      Celestial.setTextStyle(textStyle);\n      // and draw text on canvas\n      Celestial.context.fillText(d.properties.n, pt[0], pt[1]);\n    }      \n  })\n}\n```\n\nAnd 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.\n\n```js\nCelestial.display();\n```\n\nFinally, the whole map is displayed. The complete sample code is in the file [triangle.html](demo/triangle.html) in the demo folder\n\n__2. Add point sources__\n\nFirst we have to define the objects as valid geoJSON data again, as described in the readme of the [data folder](./data/). Since we're dealing with point sources, the definition is quite simple, the geometry only needs single points. If distinct point sizes are desired, a size criterion in the properties section is required, like the magnitude or extension of each object, and also a name if you want to label the objects on the map. This example uses supernova remnants filtered from the main deep space objects data file that comes with d3-celestial, but you can define your own data as below:\n    \n```js\nvar jsonSN = {\n  \"type\":\"FeatureCollection\",\n  // this is an array, add as many objects as you want\n  \"features\":[\n    {\"type\":\"Feature\",\n     \"id\":\"SomeDesignator\",\n     \"properties\": {\n       // Name\n       \"name\":\"Some Name\",\n       // magnitude, dimension in arcseconds or any other size criterion\n       \"mag\": 10,\n       \"dim\": 30\n     }, \"geometry\":{\n       // the location of the object as a [ra, dec] array in degrees [-180..180, -90..90]\n       \"type\":\"Point\",\n       \"coordinates\": [-80.7653, 38.7837]\n     }\n    }  \n  ]};\n```\n\nNext 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.  \n\n```js\nvar pointStyle = { \n      stroke: \"#f0f\", \n      width: 3,\n      fill: \"rgba(255, 204, 255, 0.4)\"\n    };\nvar textStyle = { \n      fill:\"#f0f\", \n      font: \"bold 15px Helvetica, Arial, sans-serif\", \n      align: \"left\", \n      baseline: \"bottom\" \n    };\n```\n\nNow we are ready to add the functions that do the real work of putting the data on the map.\n\n```js\nCelestial.add({file:string, type:json|raw, callback:function, redraw:function)\n```\n\nThe file argument is optional for providing an external geoJSON file; since we already defined our data, we don't need it. Type is 'line', that leaves two function definitions: the first one is called at loading, this is where we add our data to the d3-celestial data container, while the second function 'redraw' is called at every redraw event for the map. So here you need to define how to display the added object(s). Here are two different possibilities to add data to the D3 data container. Either add the data defined as a JSON-Object in-page, as below with the jsonSN object we defined before. \n\n```js\ncallback: function(error, json) {\n  if (error) return console.warn(error);\n  // Load the geoJSON file and transform to correct coordinate system, if necessary\n  var dsn = Celestial.getData(jsonSN, config.transform);\n\n  // Add to celestial objects container in d3\n  Celestial.container.selectAll(\".snrs\")\n    .data(asterism.features)\n    .enter().append(\"path\")\n    .attr(\"class\", \"snr\"); \n  // Trigger redraw to display changes\n  Celestial.redraw();\n}\n```\n\nOr 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.  \n\n```js\ncallback: function(error, json) {\n  if (error) return console.warn(error);\n  // Load the geoJSON file and transform to correct coordinate system, if necessary\n  var dsos = Celestial.getData(json, config.transform);\n\n  // Filter SNRs and add to celestial objects container in d3\n  Celestial.container.selectAll(\".snrs\")\n    .data(dsos.features.filter(function(d) {\n      return d.properties.type === 'snr'\n    }))\n    .enter().append(\"path\")\n    .attr(\"class\", \"snr\"); \n  // Trigger redraw to display changes\n  Celestial.redraw();\n}\n```\n\nHowever you add the data, as long as they receive the same class name - 'snr' in the examples above - the display method is the same, as shown below. With point data we can't rely on the map function to do all the work, we need to paint on the canvas step by step. First, check if the point is currently displayed (clip), then get the location (mapProjection), size (whatever scaling formula you like) and styling.  \n  \nNow we are ready to throw pixels at the canvas: set the styles (fill color, stroke color \u0026 width), followed by whatever canvas commands are required to draw the object shape, here a filled circle outline. And then the same for the adjacent object name offset by the previously calculated radius.  \n\n```js\nredraw: function() {\n  // Select the added objects by class name as given previously\n  Celestial.container.selectAll(\".snr\").each(function(d) {\n    // If point is visible (this doesn't work automatically for points)\n    if (Celestial.clip(d.geometry.coordinates)) {\n      // get point coordinates\n      var pt = Celestial.mapProjection(d.geometry.coordinates);\n      // object radius in pixel, could be varable depending on e.g. dimension or magnitude \n      var r = Math.pow(20 - prop.mag, 0.7); // replace 20 with dimmest magnitude in the data\n   \n      // draw on canvas\n      //  Set object styles fill color, line color \u0026 width etc.\n      Celestial.setStyle(pointStyle);\n      // Start the drawing path\n      Celestial.context.beginPath();\n      // Thats a circle in html5 canvas\n      Celestial.context.arc(pt[0], pt[1], r, 0, 2 * Math.PI);\n      // Finish the drawing path\n      Celestial.context.closePath();\n      // Draw a line along the path with the prevoiusly set stroke color and line width      \n      Celestial.context.stroke();\n      // Fill the object path with the prevoiusly set fill color\n      Celestial.context.fill();     \n\n      // Set text styles       \n      Celestial.setTextStyle(textStyle);\n      // and draw text on canvas\n      Celestial.context.fillText(d.properties.name, pt[0] + r - 1, pt[1] - r + 1);\n    }      \n  }); \n}});\n```\n\nFinally, the whole map can be displayed.   \n\n```js\nCelestial.display();\n```\n \n\n__Bonus: Avoid overlapping labels__  \n\nYou will note that there is a lot of overlap between distinct labels. Fortunately, d3 already has a solution for this: d3.geom.quadtree, which builds a hiearchical data structure ordered by proximity.\nFirst we set the closest allowed distance between two labels in pixels, get the map dimensions from Celestial.metrics, and create a quadtree object with the extent of those dimensions.\n\n```js\nvar PROXIMITY_LIMIT = 20,\n    m = Celestial.metrics(), \n    quadtree = d3.geom.quadtree().extent([[-1, -1], [m.width + 1, m. height + 1]])([]);\n```\n\nAfter proceeding as above - get the projected map position in pixelspace (pt) and draw the snr symbol - we use the quadtree.find() function to find the nearest neighbor relative to this position, and if it is more distant than our limit above, add it to quadtree and draw the label, otherwise don't.\n\n```js\nvar nearest = quadtree.find(pt);\n\nif (!nearest || distance(nearest, pt) \u003e PROXIMITY_LIMIT) { \n  quadtree.add(pt)\n  // draw the label as above\n}\n```\n\nThis will only draw non-overlapping labels and scales with zoom-level, since it checks in pixel-space and not in coordinate-space.  \n  \nNow we need just one more thing, the distance function used above, which is the standard Pythagorean square root of the sum of the differences squared function.  \n\n\n```js\n// Simple point distance function\nfunction distance(p1, p2) {\n  var d1 = p2[0] - p1[0],\n      d2 = p2[1] - p1[1];\n  return Math.sqrt(d1 * d1 + d2 * d2);\n}\n```\n  \nThe complete sample code is in the file [snr.html](demo/snr.html) in the demo folder.  \n\n### Files\n\n__GeoJSON data files__  \n(See format specification in the readme for the [data folder](./data/))  \n\n* `stars.6.json` Stars down to 6th magnitude \\[1\\]\n* `stars.8.json` Stars down to 8.5th magnitude \\[1\\]\n* `stars.14.json` Stars down to 14th magnitude (large) \\[1\\]\n* `starnames.json` Star names and designations \\[1b\\]\\[1c\\]\n* `dsos.6.json` Deep space objects down to 6th magnitude \\[2\\]\n* `dsos.14.json` Deep space objects down to 14th magnitude \\[2\\]\n* `dsos.20.json` Deep space objects down to 20th magnitude \\[2\\]\n* `dsos.bright.json` Some of the brightest showpiece DSOs of my own choosing\n* `messier.json` Messier objects \\[8\\]\n* `lg.json` Local group and Milky Way halo galaxies/globiular clusters. My own compilation \\[6\\]\n* `constellations.json` Constellation data  \\[3\\] \n* `constellations.bounds.json` Constellation boundaries \\[4\\]\n* `constellations.lines.json` Constellation lines \\[3\\]\n* `asterisms.json` Asterism data  \\[7\\]\n* `mw.json` Milky Way outlines in 5 brightness steps \\[5\\]\n* `planets.json` Keplerian Elements for Approximate Positions of the Major Planets \\[9\\]  \n__Traditional Chinese Constellations \u0026 Stars__ \n* `constellations.cn.json` Constellation data  \\[10\\] \n* `constellations.bounds.cn.json` Constellation boundaries \\[10\\]\n* `constellations.lines.cn.json` Constellation lines \\[10\\]\n* `starnames.cn.json` Star names and designations \\[10\\]\n\n__Sources__\n\n* \\[1\\] XHIP: An Extended Hipparcos Compilation; Anderson E., Francis C. (2012) [VizieR V/137D](http://cdsarc.u-strasbg.fr/viz-bin/Cat?V/137D)  \n* \\[1b\\] _Star names \u0026 designations:_  \n    HD-DM-GC-HR-HIP-Bayer-Flamsteed Cross Index (Kostjuk, 2002) [VizieR IV/27A](http://cdsarc.u-strasbg.fr/viz-bin/Cat?IV/27A)  \n FK5-SAO-HD-Common Name Cross Index (Smith 1996) [VizieR IV/22](http://cdsarc.u-strasbg.fr/viz-bin/Cat?IV/22)  \n General Catalogue of Variable Stars (Samus et.al. 2007-2013) [VizieR B/gcvs](http://cdsarc.u-strasbg.fr/viz-bin/Cat?B/gcvs)  \n Preliminary Version of the Third Catalogue of Nearby Stars (Gliese+ 1991) [VizieR V/70A](http://cdsarc.u-strasbg.fr/viz-bin/Cat?V/70A)  \n* \\[1c\\] [Stellarium skycultures data](https://github.com/Stellarium/stellarium/tree/master/po/stellarium-skycultures)  for star name translations  \n* \\[2\\] [Saguaro Astronomy Club Database version 8.1](http://www.saguaroastro.org/sac-downloads/)  \n* \\[3\\] [IAU Constellation page](http://www.iau.org/public/themes/constellations/), name positions and some line modifications by me, names in other languages from [Wikipedia](https://wiki2.org/en/88_modern_constellations_in_different_languages)  \n* \\[4\\] Catalogue of Constellation Boundary Data; Davenhall A.C., Leggett S.K. (1989) [VizieR VI/49](http://vizier.cfa.harvard.edu/viz-bin/Cat?VI/49)  \n* \\[5\\] [Milky Way Outline Catalog](http://www.skymap.com/milkyway_cat.htm), Jose R. Vieira  \n* \\[6\\] Lots of sources, see [blog](http://armchairastronautics.blogspot.com/p/milky-way-halo.html) [pages](http://armchairastronautics.blogspot.com/p/local-group.html) for complete list  \n* \\[7\\] [Saguaro Astronomy Club Asterisms](http://saguaroastro.org/sac-downloads/) \\(scroll down\\)  \n* \\[8\\] [Messier Objects with Data](http://messier.seds.org/data.html), H.Frommert/seds.org  \n* \\[9\\] [Keplerian Elements for Approximate Positions of the Major Planets](https://ssd.jpl.nasa.gov/?planet_pos)  \n* \\[10\\] [Stellarium skycultures data](https://github.com/Stellarium/stellarium/tree/master/skycultures/chinese) for traditional Chinese constellations  \n  \nAll data converted to GeoJSON at J2000 epoch, positions converted from 0...24h right ascension to -180...180 degrees longitude as per GeoJSON requirements, so 0...12h becomes 0...180 degrees, and 12...24h becomes -180...0 degrees.  \n\n__Other files__\n\n* `celestial.js` main javascript object\n* `celestial.min.js`  minified javascript\n* `celestial.tar.gz`  data, minified script and viewer, all you need for local display \n* `LICENSE`\n* `readme.md` this file\n* `celestial.css` stylesheet\n* `lib/d3.*.js`  necessary d3 libraries\n* `src/*.js` source code for all modules\n\nThanks to Mike Bostock and Jason Davies for [D3.js](http://d3js.org/) and [d3.geo.projections](https://github.com/d3/d3-geo-projection).\nAnd also thanks to Jason Davies for [d3.geo.zoom](http://www.jasondavies.com/maps/rotate/), which saved me some major headaches in figuring out how to rotate/zoom the map.\n\nReleased under [BSD License](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fofrohn%2Fd3-celestial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fofrohn%2Fd3-celestial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fofrohn%2Fd3-celestial/lists"}