typescriptgoogle-mapssvggoogle-maps-advanced-marker-element

Remove or move frame that's drawn around focused AdvancedMarkerElement


I had an issue with centering the AdvancedMarkerElement in this question: Draw AdvancedMarkerElement on center of its position

The solution worked, but only for the marker itself. But when focused, the marker draws a frame around the original (non-transformed) position of the marker.

Frame is not transformed

I would need the frame removed or properly transformed to be centered again.

I am using Firefox.

const HANDLE_ICON =
  '<svg xmlns="http://www.w3.org/2000/svg" transform="translate(0 8)" height="16px" viewBox="0 -960 960 960" width="16px" fill="#000"><path d="M214-74q-59.12 0-99.56-40.44Q74-154.88 74-214v-532q0-59.13 40.44-99.56Q154.88-886 214-886h532q59.13 0 99.56 40.44Q886-805.13 886-746v532q0 59.12-40.44 99.56Q805.13-74 746-74H214Z"/>  </svg>';


async function initMap() {
  // Request libraries when needed, not in the script tag.
  const {
    Map
  } = await google.maps.importLibrary("maps");
  const {
    AdvancedMarkerElement
  } = await google.maps.importLibrary("marker");

  const latlng = {
    lat: 10,
    lng: 12
  }
  const map = new Map(document.getElementById("map"), {
    zoom: 16,
    center: latlng,
    mapId: "4504f8b37365c3d0",
    mapTypeId: google.maps.MapTypeId.SATELLITE
  });

  const parser = new DOMParser();
  const pinSvg = parser.parseFromString(
    HANDLE_ICON,
    "image/svg+xml"
  ).documentElement;

  // Create
  const marker = new AdvancedMarkerElement({
    map: map,
    position: latlng,
    content: pinSvg,
    gmpDraggable: true,
    gmpClickable: true,
  });
}

initMap()
#map {
  height: 250px;
}
<div id="map"></div>


<!-- prettier-ignore -->
<script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk", v: "beta"});</script>

I don't really see why it would be drawn. I can't specify it to not draw the frame via Google Maps API.

I tried Chromium too which gives a similar result in the beginning but after some dragging it doesnt draw it anymore, very inconsistent.


Solution

  • I have checked a few Advanced Markers examples from the official docs and noticed that the markers are actually not properly pointing to the right locations... so obviously they didn't need any kind of repositioning of either SVG or HTML elements, which might explain why this doesn't seem to be documented anywhere at this point (and why the official examples don't have broken outlines).

    As I said in a comment, I see no benefit of using SVG for such a simple graphic element so I created a similar marker with an HTML element.

    It seems that adding a bottom margin (negative margin in this case) on the marker HTML instead of using a CSS translation solves the issue. The focus outline is aligned with the marker.

    I can't confirm though that this is the recommended way to go but it seems to work and to be properly centered on the location.

    Edit:

    I just tested in Safari and guess what, the outline is broken (the bottom is missing). So this is probably not the way to go and it feels like a bug in the implementation.

    The .xxx-marker-view elements already have CSS transform (translate) applied to align the markers to the bottom center by default. So, applying another and opposite transform on the Marker content feels quite wrong.

    I found this related bug in the issue tracker and opened another one regarding the focus outlines specifically.

    async function initMap() {
    
      // Request needed libraries.
      const { Map } = await google.maps.importLibrary("maps");
      const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
      const center = {
        lat: 0,
        lng: 0
      }
      
      const map = new Map(document.getElementById("map"), {
        center: center,
        zoom: 14,
        mapId: "4504f8b37365c3d0",
      });
    
      const htmlMarker = document.createElement('div')
      htmlMarker.className = 'black-square';
    
      let marker = new google.maps.marker.AdvancedMarkerElement({
        map: map,
        position: center,
        content: htmlMarker,
        gmpDraggable: true,
        gmpClickable: true
      });
    
      let defaultMarker = new google.maps.marker.AdvancedMarkerElement({
        map: map,
        position: center
      });
    }
    
    initMap();
    #map {
      height: 150px;
    }
    
    .black-square {
      width: 16px;
      height: 16px;
      border-radius: 3px;
      background: black;
      margin-bottom: -8px;
    }
    <div id="map"></div>
    
    <!-- prettier-ignore -->
    <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
            ({key: "AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk", v: "weekly"});</script>