Terion
Terion

Reputation: 2506

css-scaled google maps click incorrect coordinates

I have a Google Maps map inserted in a css-scaled container. Due to project specifics this cannot be avoided. I need to track clicks coords on this map, but being scaled map sets incorrect coordinates (see the snippet).

How can be this fixed? I have no ideas at the moment :(

const map = new google.maps.Map(document.querySelector('#map'), {
  center: {lat: 48.7, lng: 31},
  zoom: 6
});

google.maps.event.addListener(map, 'click', (event)=> {
  const marker = new google.maps.Marker({
    position: event.latLng,
    map: map
  });
});
html, body {
    height: 100%;
  }
.container {
  width: 800px;
  height: 600px;
  transform: scale(1.2);
  }
#map {
  width: 100%;
  height: 100%;
  }
<script src="https://maps.googleapis.com/maps/api/js?.js"></script>
<div class="container">
<div id="map"></div>
</div>

Upvotes: 0

Views: 459

Answers (3)

aards
aards

Reputation: 83

I also had this issue and the above solutions didn't work for me because:

  • @Terion's "point2LatLng" function didn't seem to place the marker in the correct location
  • @Terion's use of a virtual iframe meant that you can't drag the map, which severely restricted the user experience.

However I did find a way to do it: I put the map div inside a container which I effectively un-scaled with this JS, loaded after all other JS:

//Function: Unscale the map Container
function unscaleMap(scale){
    var unscale = Math.round(10000/(scale * 1))/10000,
        rescale = Math.round(10000 * (100 / unscale))/10000;
    document.getElementById("fs_mapContainer").style.transform = "scale("+unscale+")";
    document.getElementById("fs_mapContainer").style.width = rescale + "%";
    document.getElementById("fs_mapContainer").style.height = 80 * scale + "vh";
}

And CSS:

.map_container {position: relative; transform-origin: 0 0; box-sizing: border-box;}
#map {width: 100%; height: 100%}

Upvotes: 0

Terion
Terion

Reputation: 2506

This answer works, but being scaled map works very bad, many coordinate-related functions don't wok correctly. But there is a workaround: place the map in a virtual iframe:

    const iframe = this.$el.querySelector('iframe');
    iframe.contentWindow.document.open();
    iframe.contentWindow.document.write('<div id="map" style="width: 100%; height: 100%"></div>');
    iframe.contentWindow.document.close();

    const mapContainer = iframe.contentWindow.document.querySelector('#map');
    const map = new gmaps.Map(mapContainer, {
              center: {lat: 48.7, lng: 31},
              zoom: 6
            });

There are no x-origin restrictions and you can manipulate with iframe content how you want. And with it, even if parent container is scaled, everything works fine

Upvotes: 1

Terion
Terion

Reputation: 2506

Ok, figured out how to correct fix (this is when transformation center is 0,0)

function point2LatLng(point, transformScale, map) {
    var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
    var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
    var scale = Math.pow(2, map.getZoom());
    var worldPoint = new google.maps.Point(point.x / transformScale / scale + bottomLeft.x, point.y / transformScale / scale + topRight.y);
    return map.getProjection().fromPointToLatLng(worldPoint);
  }

gmaps.event.addListener(this.map, 'click', (event)=> {
          let transformMatrix = window.getComputedStyle(this.$el.closest('.container')).transform.match(/^matrix\((.+)\)$/)[1].split(', ');
          let transformScale = parseFloat(transformMatrix[0]);
          var marker = new gmaps.Marker({
              position: point2LatLng(event.pixel, transformScale, this.map),
              map: this.map
          });
        });

Upvotes: 1

Related Questions