javascripthtmlgoogle-maps-api-3

Google Maps API: Move map center to a position on my page?


maybe there is a solution for this:

I'm using the Gmap api to embed a map undernaeth an overlay that I have on top of my map. The overlay has a little arrow on the right side and I want my map marker to be positioned at this point (or a few pixels beside it)

I know it would be possible to use a GMaps Infowindow, but I have it this way.

So I'm able to use $("#arrow").offset() in order to get its position on the page, but I don't know how to move or pan the map center to this pixel-destination.

window.onload = function() {
    var myOptions = {
        center: new google.maps.LatLng(47.259998, 11.398032),
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true
    };

    var map = new google.maps.Map(document.getElementById("map"), myOptions);

    var marker = new google.maps.Marker({
        position: new google.maps.LatLng(47.260071, 11.404705),
        map: map,
    });

    console.log( $("#arrow").offset().top );
}

enter image description here


Update:

This is the code I have in my page-template right now. I have on last problem though. If my page has a width of lets say 1440px the position of the marker relative to my little arrow works just fine: enter image description here

However as soon as I resize the page to a smaller width and load the page again the marker is behind the overlay and not positioned relative to the little arrow.

enter image description here

google.maps.event.addDomListener(window, 'load', initMap);

window.onresize = function() {
    positionMap();
}

function initMap() {
    var myOptions = {
        center: new google.maps.LatLng(47.260071, 11.404705),
        zoom: 17,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true,
        draggable: false,
        mapTypeControl: false,
        zoomControl: false,
        scaleControl: false,
        scrollwheel: false
    };

    var map = new google.maps.Map(document.getElementById("map"), myOptions);

    var marker = new google.maps.Marker({
        position: new google.maps.LatLng(47.260071, 11.404705),
        map: map,
        title: 'Österreichisches Rotes Kreuz Innsbruck'
    });
}

function positionMap() {
    var arrowPos = $("#map-center").position();
    console.log(arrowPos);

    var getPixelOffset = function(map, marker) {
        // Calculate marker position in pixels form upper left corner
        var scale = Math.pow(2, map.getZoom());
        var nw = new google.maps.LatLng(
            map.getBounds().getNorthEast().lat(),
            map.getBounds().getSouthWest().lng()
        );
        var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
        var worldCoordinate = map.getProjection().fromLatLngToPoint(marker.getPosition());
        var pixelOffset = new google.maps.Point(
            Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
            Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
        );
        return pixelOffset;
    };

    // Wait until the map is initialized
    var listener = google.maps.event.addListener(map, "idle", function() { 
        var pixelOffset = getPixelOffset(map, marker);
        
        // Do the pan
        map.panBy( Math.abs( pixelOffset.x - ( arrowPos.left ) - 150 ),
                 Math.abs( pixelOffset.y - ( arrowPos.top ) ) - 50 );
        
        google.maps.event.removeListener(listener); 
    });
}

Solution

  • One approach is to use map.getProjection().fromLatLngToPoint() to find the pixel position of the marker inside the map, then subtract your $("#arrow").offset() from the marker position and call map.panBy() to move the marker by the calculated difference.

    Here's the demo in which the marker is moved to the sample position { top: 50, left: 100 }:

    var myOptions = {
            center: new google.maps.LatLng(47.259998, 11.398032),
            zoom: 17,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            disableDefaultUI: true
        };
    
    var map = new google.maps.Map(document.getElementById("map"), myOptions);
    
    var marker = new google.maps.Marker({
            position: new google.maps.LatLng(47.260071, 11.404705),
            map: map,
            title: 'Hello World!'
        });
    
    
    // Replace this with call to $("#arrow").offset()
    var arrowPos = { top: 50, left: 100 };
    
    var getPixelOffset = function(map, marker) {
        // Calculate marker position in pixels form upper left corner
        var scale = Math.pow(2, map.getZoom());
        var nw = new google.maps.LatLng(
            map.getBounds().getNorthEast().lat(),
            map.getBounds().getSouthWest().lng()
        );
        var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
        var worldCoordinate = map.getProjection().fromLatLngToPoint(marker.getPosition());
        var pixelOffset = new google.maps.Point(
            Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
            Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
        );
        return pixelOffset;
    };
    
    // Wait until the map is initialized
    var listener = google.maps.event.addListener(map, "idle", function() { 
        var pixelOffset = getPixelOffset(map, marker);
        
        // Do the pan
        map.panBy(Math.abs(pixelOffset.x - arrowPos.left),
                 Math.abs(pixelOffset.y - arrowPos.top));
        
        google.maps.event.removeListener(listener); 
    });
    html,
    body,
    #map {
        display: block;
        width: 100%;
        height: 100%;
    }
    
    #map {
        background: #58B;
    }
    <script src="http://maps.google.com/maps/api/js?sensor=true&.js"></script>
    <div id="map"></div>

    Also, note that you have to do that when the map is fully loaded, i.e. in the idle event handler. Otherwise (that's what I experienced) the getProjection() method might be unavailable.

    References: