22

I am hoping someone can point me in the right direction.

I have a Google Map that loads markers from an XML file, along with various other map elements, works great. However I now need to overlay a PNG image onto the map.

I have tried for hours to correctly align the PNG over the top of the site but just cannot find the exact two co-ordinates I need (south-west and north-east). Is there a tool for doing this? Ideally upload the image and drag the corners to fit, and it outputs the two co-ordinates (lat/lng) you need?

I have tried using this tool: http://overlay-tiler.googlecode.com/svn/trunk/upload.html - but it has three contact points.

I have also tried using this tool: http://www.birdtheme.org/useful/customoverlay.html - but you cannot resize the image once uploaded to the map and you get one chance at clicking the south-west marker!

I can also use Google Earth to align the PNG perfectly, but I can't see a way of outputting the lat/lng points.

Any advice would be much appreciated.

LearnCode
  • 221
  • 1
  • 2
  • 3
  • It's not clear whether upload/drag capability is for development purposes or as an end user feature? – Beetroot-Beetroot Jul 03 '13 at 04:43
  • @Beetroot-Beetroot I would think of it as a once off end user feature like align the picture once and then save the required data and just show the image @ that rotation or scale each time – GardenRouteGold Jul 04 '13 at 12:23
  • Re "use Google Earth to align the PNG perfectly, but I can't see a way of outputting the lat/lng points." I believe you output as KML, and extract the numbers from that. See Ground Overlays in Keyhole Markup Language tutorial: https://developers.google.com/kml/documentation/kml_tut?hl=it – ToolmakerSteve Sep 17 '14 at 05:32

3 Answers3

28

Heres a working example of André Dion's explanation.

http://jsfiddle.net/4cWCW/3/

var overlay;

DebugOverlay.prototype = new google.maps.OverlayView();

function initialize() {
  var mapOptions = {
    zoom: 15,
    center: new google.maps.LatLng(40.743388,-74.007592)
  };

  var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
  var swBound = new google.maps.LatLng(40.73660837340877, -74.01852328);
  var neBound = new google.maps.LatLng(40.75214181, -73.99661518216243);
  var bounds = new google.maps.LatLngBounds(swBound, neBound);

   console.log(map);
  var srcImage = 'http://robincwillis.com/top/splash/04.jpg';

  overlay = new DebugOverlay(bounds, srcImage, map);

  var markerA = new google.maps.Marker({
            position: swBound,
            map: map,
            draggable:true
        });

    var markerB = new google.maps.Marker({
        position: neBound,
        map: map,
        draggable:true
    });

    google.maps.event.addListener(markerA,'drag',function(){

        var newPointA = markerA.getPosition();
        var newPointB = markerB.getPosition();
        var newBounds =  new google.maps.LatLngBounds(newPointA, newPointB);
        overlay.updateBounds(newBounds);
    });

  google.maps.event.addListener(markerB,'drag',function(){

      var newPointA = markerA.getPosition();
      var newPointB = markerB.getPosition();
      var newBounds =  new google.maps.LatLngBounds(newPointA, newPointB);
      overlay.updateBounds(newBounds);
  });

    google.maps.event.addListener(markerA, 'dragend', function () {

        var newPointA = markerA.getPosition();
        var newPointB = markerB.getPosition();
        console.log("point1"+ newPointA);
        console.log("point2"+ newPointB);
    });

    google.maps.event.addListener(markerB, 'dragend', function () {
        var newPointA = markerA.getPosition();
        var newPointB = markerB.getPosition();
        console.log("point1"+ newPointA);
        console.log("point2"+ newPointB);
    });

}

function DebugOverlay(bounds, image, map) {

  this.bounds_ = bounds;
  this.image_ = image;
  this.map_ = map;
  this.div_ = null;
  this.setMap(map);
}

DebugOverlay.prototype.onAdd = function() {

  var div = document.createElement('div');
  div.style.borderStyle = 'none';
  div.style.borderWidth = '0px';
  div.style.position = 'absolute';
  var img = document.createElement('img');
  img.src = this.image_;
  img.style.width = '100%';
  img.style.height = '100%';
  img.style.opacity = '0.5';
  img.style.position = 'absolute';
  div.appendChild(img);
  this.div_ = div;
  var panes = this.getPanes();
  panes.overlayLayer.appendChild(div);
};

DebugOverlay.prototype.draw = function() {
  var overlayProjection = this.getProjection();
  var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
  var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());
  var div = this.div_;
  div.style.left = sw.x + 'px';
  div.style.top = ne.y + 'px';
  div.style.width = (ne.x - sw.x) + 'px';
  div.style.height = (sw.y - ne.y) + 'px';
};


DebugOverlay.prototype.updateBounds = function(bounds){
    this.bounds_ = bounds;
    this.draw();
};

DebugOverlay.prototype.onRemove = function() {
  this.div_.parentNode.removeChild(this.div_);
  this.div_ = null;
};

initialize();
Robin
  • 686
  • 1
  • 9
  • 18
9

I had to solve this exact problem for a client not long ago. My solution was to simply create two markers; one at each LatLng for the overlay's LatLngBounds that, when moved, would update the overlay and log the LatLndBounds to the console for me to reference. I also added reticules (vertical and horizontal lines) that are shown when dragging a marker so it was easier to visually position the overlay.

I cannot share the code from the solution with you, but it involves working with an OverlayView in order to convert LatLng coordinates to and from pixels via MapCanvasProjection.

Like you, we didn't need this functionality for end-users so I added a "authoring mode" that's toggled by providing a debug parameter to the solution's query string.

André Dion
  • 21,269
  • 7
  • 56
  • 60
  • Yea i also have a mode that is only triggered once and only if a user has enough permission to perform the action So to pick your brain a small bit You Create the bottom left marker Then the user adds the top right marker User sees that the image is like 3 / 10 / 20 degrees off so they drag the bottom left marker upwards and then you just redraw the image after that – GardenRouteGold Jul 08 '13 at 07:09
  • 1
    By moving either NE or SW markers, you skew the image overlay. I forgot to mention that as a prerequisite, the image used for the overlay needs to be in the same orientation as the map (i.e., the top of the image is North). – André Dion Jul 08 '13 at 19:12
  • are you maybe the same person that built [thannmap on appspot](http://thannmap.appspot.com/) ? Also did you have to do much Trig in this Solution? I am also wondering if building this solution would be similar to this [google/overlays#CustomOverlays](https://developers.google.com/maps/documentation/javascript/overlays#CustomOverlays) solution ? exept you just replace the hard coded co-ords of the bot left / top right with your user specified markers co-ords ? – GardenRouteGold Jul 09 '13 at 07:49
  • No, that wasn't me. My solution doesn't involve any trigonometry, though it did subclass `google.maps.CustomOverlay`. – André Dion Jul 09 '13 at 11:50
  • i did you what did but like when you put the NE marker Lower than the SW marker the image appears to be bellow the bounding box :( [something like this](http://overlay-tiler.googlecode.com/svn/trunk/edit.html?overlay=http%3A%2F%2Fwww.google.com%2Fintl%2Fen_com%2Fimages%2Fsrpr%2Flogo3w.png&lat=-34.0391543474887&lng=23.042416499999945&z=11) would be like amazing – GardenRouteGold Jul 19 '13 at 07:28
2

I like to use the one located here:

http://googlemapsapi.blogspot.com/2007/05/v280-making-image-overlays-easy-with.html

It's far from ideal, and it generates Google Maps version 2 API code, but you can still use the logitude/latitude coordinates.

bmsauer
  • 105
  • 9