Google Maps: Get click or marker (x,y) pixel coordinates inside marker click listener

12,330

Solution 1

A marker click event returns a MouseClickEvent

The only documented property of a MouseClickEvent is:

latLng LatLng The latitude/longitude that was below the cursor when the event occurred.

To convert that into a pixel position use the fromLatLngToContainerPixel method of MapCanvasProjection:

    google.maps.event.addListener(marker, 'click', function (e) {
       var point = overlay.getProjection().fromLatLngToDivPixel(e.latLng); 
            info.style.left = point.x + 'px';
            info.style.top = point.y + 'px';
            info.style.display = 'block';
    });

working fiddle

code snippet:

var geocoder;
var map;
var overlay;

function initialize() {
    var map = new google.maps.Map(
    document.getElementById("map_canvas"), {
        center: new google.maps.LatLng(37.4419, -122.1419),
        zoom: 13,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    var marker = new google.maps.Marker({
        map: map,
        draggable: true,
        position: map.getCenter()
    });

    google.maps.event.addListener(map, 'projection_changed', function () {
        overlay = new google.maps.OverlayView();
        overlay.draw = function () {};
        overlay.setMap(map);

        var info = document.getElementById('myinfo');
        google.maps.event.addListener(marker, 'click', function (e) {
           var point = overlay.getProjection().fromLatLngToContainerPixel(e.latLng); 
                info.style.left = (point.x - 100)+ 'px';
                info.style.top = (point.y) + 'px';
                info.style.display = 'block';
        });
        google.maps.event.addListener(map, 'center_changed', function (e) {
            var point = overlay.getProjection().fromLatLngToContainerPixel(marker.getPosition()); 
                info.style.left = (point.x - 100)+ 'px';
                info.style.top = (point.y) + 'px';
                info.style.display = 'block';
        });
                google.maps.event.addListener(marker, 'drag', function (e) {
           var point = overlay.getProjection().fromLatLngToContainerPixel(marker.getPosition()); 
                info.style.left = (point.x - 100)+ 'px';
                info.style.top = (point.y) + 'px';
                info.style.display = 'block';
        });
        
    });
}
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
div.info {
  position: absolute;
  z-index: 999;
  width: 200px;
  height: 50px;
  display: none;
  background-color: #fff;
  border: 3px solid #ebebeb;
  padding: 10px;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas" style="border: 2px solid #3872ac;"></div>
<div id="myinfo" class="info">
  <p>I am a div on top of a google map ..</p>
</div>

Solution 2

Here is how you get the pixel location:

function getPixelLocation(currentLatLng) {

        var scale = Math.pow(2, map.getZoom());
        // The NorthWest corner of the current viewport corresponds
        // to the upper left corner of the map.
        // The script translates the coordinates of the map's center point
        // to screen coordinates. Then it subtracts the coordinates of the
        // coordinates of the map's upper left corner to translate the 
        // currentLatLng location into pixel values in the <div> element that hosts the map.
        var nw = new google.maps.LatLng(
            map.getBounds().getNorthEast().lat(),
            map.getBounds().getSouthWest().lng()
        );
        // Convert the nw location from geo-coordinates to screen coordinates
        var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
        // Convert the location that was clicked to screen coordinates also
        var worldCoordinate = map.getProjection().fromLatLngToPoint(currentLatLng);
        var currentLocation = new google.maps.Point(
            Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
            Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
        );

        console.log(currentLocation);
        return currentLocation;
    }
Share:
12,330
Abram
Author by

Abram

I am the founder and lead developer at HearingTracker.com, America's #1 hearing aid shopping resource. "I've been working on the Rails code, all the live long day..."

Updated on June 11, 2022

Comments

  • Abram
    Abram almost 2 years

    I am trying to display completely custom info windows over map markers on marker click. I have successfully implemented this answer to get a div to show over a map-canvas click... but I am not able to replicate it on a marker click.

    Is it possible to get the markers pixel position inside of the marker click function, and suppress the normal infowindow to show the desired custom infowindow?

    I tried this:

          google.maps.event.addListener(marker, 'click', function(args) {
            var x=args.pixel.x+$('#map').offset().left; //we clicked here
            var y=args.pixel.y;
    
            info.style.left=x+'px';
            info.style.top=y+'px';
            info.style.display='block';
          });
    

    but in the console, I see:

    Uncaught TypeError: Cannot read property 'x' of undefined