Monday, November 18, 2019

D3-Celestial Geolocator

I was looking for a simple graphical location-selector, a globe that can be spun, zoomed in and clicked on to get an approximate location. I found none so obviously I had to make my own. A good starting point was planetary.js which already takes care of the spinnable and zoomable globe and is pretty easy to extend with plugins. See my fork for details about the mouse-actions plugin.

All the work is done in a callback function for the mouse actions mousedown and mouseup. We could just use click, but that would also cause a positioning update on dragging actions on the globe. Only updating when the mouse coordinates don't change between down and up takes care of that. The rest is pretty straight forward, take mouse coordinates, calculate geographic position with the d3.js function projection.invert, and if that is valid (i.e. inside the globe) update the geolocation of the sky view.

  globe.loadPlugin(mouse({
    onMousedown: function() {
      var x = d3.event.offsetX,
          y = d3.event.offsetY;
      position = [x, y];
    },
    onMouseup: function() {
      var x = d3.event.offsetX,
          y = d3.event.offsetY,
          format = d3.format("+.3f");
      if (position[0] !== x || position[1] !== y) return;

      var pos = this.projection.invert([x,y]);
      if (!isNaN(pos[0])) {
        // latitude, longitude convention is the opposite for sky coordinates
        Celestial.skyview({"location": [format(pos[1]), format(pos[0])]});
      }   
      return pos;
    }
  }));

Time zones are not taken into account yet, so the result is not necessarily valid. That will be fixed later, as well as putting a position marker on the globe, showing the current terminator between day and night, and optionally also show the current sky state on the current view changing between blue and transparent.

[See part II: Sky color.]

No comments:

Post a Comment