Sunday, August 25, 2019

D3-Celestial showboating

Position (RA / Dec): - / - (Hold down mouse button to stop animation)
🔴 Show the colors!
🠋 Download image

Showing off some new features and howtos for d3.celstial. First setting the Color of DSOs. The new settings below allow to display alle the deep space objects in a uniform default color if the 'colors' setting is set to false in the configuration-section under 'dsos'. The colr is determined by the 'fill' and 'stroke' properties.

  dsos: {
    colors: false,  // Show DSOs in symbol colors if true, use style settings below if false
    style: { fill: "#cccccc", stroke: "#cccccc", width: 2, opacity: 1 }, // Default style for dsos
  }

Second, how to convert cursor position to map coordinates. For this we need the function invert that is implemented for every map projection. If it gets valid x/y screen coordinates relative to the upper left corner of the map (that's why offsetLeft/Top are subtracted first [Correction: Turns out offsetX/Y does the trick]), it returns the sky position in decimal degrees. Caveat: A position outside of the projected map returns [NaN, NaN].

  function getPosition(e) {
    var p = document.getElementById ('celestial-map17').getBoundingClientRect(),
        x = e.offsetX,
        y = e.offsetY,
        inv = Celestial.mapProjection.invert([x, y]);
    return inv; // [right ascension -180...180 degrees, declination -90...90 degrees]
  }
  document.getElementById('celestial-map17').addEventListener('mousemove', getPosition, false);
  

If you want to pretty print the coordinates in hms and dms as above, here are the conversion functions for your convenience:

  function deg2hms (deg) {
    if (deg === null || isNaN(parseFloat(deg))) return;
    var ra = deg < 0 ? (deg + 360) / 15 : deg / 15, 
       h = Math.floor (ra),
       rest1 = (ra - h) * 60,
       m = Math.floor(rest1),
       rest2 = (rest1 - m) * 60;
       s = Math.round(rest2);
    return '' + pad(h) + 'ʰ ' + pad(m) + 'ᵐ ' + pad(s) + 'ˢ';
  }
  function deg2dms (deg) {
    if (deg === null || isNaN(parseFloat(deg))) return;
    var d = Math.floor (deg),
       rest1 = (deg - d) * 60,
       m = Math.floor(rest1),
       rest2 = (rest1 - m) * 60;
       s = Math.round(rest2);
    return '' + pad(d) + '° ' + pad(m) + '′ ' + pad(s) + '″';
  }

  function pad(n) { 
    if (n < 0) return n > -10 ? '-0' + Math.abs(n) : n;
    return n < 10 ? '0' + n : n; 
  }

And last a simple added functionality, a download link that saves the current canvas content as an image.

  var button = document.getElementById('btnDownload');
  // Set the file name to your liking, e.g. add the displayed date/time
  button.setAttribute('download', 'd3-celestial.png');
  button.addEventListener('click', function (e) {
    var canvas = document.querySelector('#celestial-map canvas'),
        // To get a download instead of image display, according to stack overflow 
        dataURL = canvas.toDataURL('image/png').replace('image/png', 'image/octet-stream');
    button.href = dataURL;
  });

2 comments: