Search code examples
javascriptgoogle-maps-api-3google-maps-markers

Showing multiple AdvancedMarkerElements with custom content


I have four pins on my map:

async function initMap() {
  const {PinElement} = await google.maps.importLibrary("marker")
  const {AdvancedMarkerElement} = await google.maps.importLibrary("marker")
  const {Map} = await google.maps.importLibrary("maps");
  const map = new Map(document.getElementById("map"), {
    center: { lat: 17.0969451, lng: -89.0734218 },
    zoom: 9,
    mapId: 'my_map',
  });

  const L2083875 = { lat: 17.1010277, lng: -89.0770841 };
  const marker0 = new AdvancedMarkerElement({position: L2083875, map: map, });

  const L615687 = { lat: 17.1074, lng: -89.07398 };
  const marker1 = new AdvancedMarkerElement({position: L615687, map: map, });

  const L614723 = { lat: 17.09582, lng: -89.06938 };
  const marker2 = new AdvancedMarkerElement({position: L614723, map: map, });

  const L5421822 = { lat: 17.0835327, lng: -89.0732431 };
  const marker3 = new AdvancedMarkerElement({position: L5421822, map: map, });
}

This works correctly and displays four markers with the default "content".

I would like to display two pins in one color, and two pins in another color, so I added two PinElements and specified the content for each marker, per https://developers.google.com/maps/documentation/javascript/advanced-markers/basic-customization#change_the_background_color.

  const pinGlyph0 = new PinElement({
    background: "#EB3324",
    borderColor: "#EB3324",
  });

  const pinGlyph1 = new PinElement({
    background: "#FFFD55",
    borderColor: "#FFFD55",
  });

  const L2083875 = { lat: 17.1010277, lng: -89.0770841 };
  const marker0 = new AdvancedMarkerElement({position: L2083875, map: map, content: pinGlyph0.element,});

  const L615687 = { lat: 17.1074, lng: -89.07398 };
  const marker1 = new AdvancedMarkerElement({position: L615687, map: map, content: pinGlyph0.element,});

  const L614723 = { lat: 17.09582, lng: -89.06938 };
  const marker2 = new AdvancedMarkerElement({position: L614723, map: map, content: pinGlyph1.element,});

  const L5421822 = { lat: 17.0835327, lng: -89.0732431 };
  const marker3 = new AdvancedMarkerElement({position: L5421822, map: map, content: pinGlyph1.element,});

I expected two markers in the first color and two markers in the second color, but only one marker of each color is displayed. Why am I only getting one marker per color?


Solution

  • You must assign a new PinElement for each AdvancedMarker content props

    A DOM element can only be in one place at a time. Since a PinElement represents a seperate DOM element, you cannot reuse it for each AdvancedMarker elements just like how you have shown in your code. Because if you do so, it will just remove it from its first parent and append it to the next one, which explains why only 2 markers are shown when you reuse the two PinElement in your sample.

    Reference Documentation specifically says this:

    "AdvancedMarkerElement does not clone the passed-in DOM element. Once the DOM element is passed to an AdvancedMarkerElement, passing the same DOM element to another AdvancedMarkerElement will move the DOM element and cause the previous AdvancedMarkerElement to look empty."

    So the solution would be to create a new PinElement unique for each AdvancedMarker instantiation like so:

    const pinGlyphRed1 = new PinElement({
      background: "#EB3324",
      borderColor: "#EB3324"
    });
    
    const pinGlyphRed2 = new PinElement({
      background: "#EB3324",
      borderColor: "#EB3324"
    });
    
    const pinGlyphYellow1 = new PinElement({
      background: "#FFFD55",
      borderColor: "#FFFD55"
    });
    
    const pinGlyphYellow2 = new PinElement({
      background: "#FFFD55",
      borderColor: "#FFFD55"
    });
    

    And then you put each of them as a value in the content props in each of the AdvancedMarker:

    const L2083875 = { lat: 17.1010277, lng: -89.0770841 };
    const marker0 = new AdvancedMarkerElement({
      position: L2083875,
      map: map,
      content: pinGlyphRed1.element
    });
    
    const L615687 = { lat: 17.1074, lng: -89.07398 };
    const marker1 = new AdvancedMarkerElement({
      position: L615687,
      map: map,
      content: pinGlyphRed2.element
    });
    
    const L614723 = { lat: 17.09582, lng: -89.06938 };
    const marker2 = new AdvancedMarkerElement({
      position: L614723,
      map: map,
      content: pinGlyphYellow1.element
    });
    
    const L5421822 = { lat: 17.0835327, lng: -89.0732431 };
    const marker3 = new AdvancedMarkerElement({
      position: L5421822,
      map: map,
      content: pinGlyphYellow2.element
    });
    

    With that, the color should be properly assigned for each Marker.

    Here's the full code snippet for reference

    async function initMap() {
      const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary(
        "marker"
      );
      const { Map } = await google.maps.importLibrary("maps");
      const map = new Map(document.getElementById("map"), {
        center: { lat: 17.0969451, lng: -89.0734218 },
        zoom: 13,
        mapId: "my_map"
      });
    
    const pinGlyphRed1 = new PinElement({
      background: "#EB3324",
      borderColor: "#EB3324"
    });
    
    const pinGlyphRed2 = new PinElement({
      background: "#EB3324",
      borderColor: "#EB3324"
    });
    
    const pinGlyphYellow1 = new PinElement({
      background: "#FFFD55",
      borderColor: "#FFFD55"
    });
    
    const pinGlyphYellow2 = new PinElement({
      background: "#FFFD55",
      borderColor: "#FFFD55"
    });
    
    const L2083875 = { lat: 17.1010277, lng: -89.0770841 };
    const marker0 = new AdvancedMarkerElement({
      position: L2083875,
      map: map,
      content: pinGlyphRed1.element
    });
    
    const L615687 = { lat: 17.1074, lng: -89.07398 };
    const marker1 = new AdvancedMarkerElement({
      position: L615687,
      map: map,
      content: pinGlyphRed2.element
    });
    
    const L614723 = { lat: 17.09582, lng: -89.06938 };
    const marker2 = new AdvancedMarkerElement({
      position: L614723,
      map: map,
      content: pinGlyphYellow1.element
    });
    
    const L5421822 = { lat: 17.0835327, lng: -89.0732431 };
    const marker3 = new AdvancedMarkerElement({
      position: L5421822,
      map: map,
      content: pinGlyphYellow2.element
    });
    }
    
    initMap = initMap();
    /* 
     * Always set the map height explicitly to define the size of the div element
     * that contains the map. 
     */
    #map {
      height: 100vh;
    }
    
    /* 
     * Optional: Makes the sample page fill the window. 
     */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    [class$="api-load-alpha-banner"] {
      display: none;
    }
    <html>
      <head>
        <title>Default Advanced Marker</title>
        <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
    
        <link rel="stylesheet" type="text/css" href="./styles.css" />
        <script type="module" src="./index.js"></script>
      </head>
      <body>
        <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>
      </body>
    </html>

    I hope this helps!