Search code examples
javascriptgoogle-mapsgoogle-apimigrationgoogle-maps-markers

Google advanced marker animation don't work


I'm trying to migrate my custom map markers to the new advanced marker library, seems the animation options is no more available, it give me this error:

Unknown property 'animation' of AdvancedMarkerElement

I checked the documentation and the animation options is still there but nothing is mentioned about how to migrate the animation option.

google marker documentation

newMarker = new google.maps.marker.AdvancedMarkerElement({
    position: markerOpposto,
    map: map,
    content: imageIcon,
    title: "New position",
    animation: google.maps.Animation.BOUNCE 
})

Solution

  • Use CSS animation for Advanced Markers

    First thing that we need to understand about Advanced Marker is that it is no longer an MVC Object unlike the Legacy Markers. The Animation constants (BOUNCE and DROP) that existed on the Legacy Marker are no longer available.

    That is because, as per the documentation, the Advanced Marker class now extends HTMLElement. This means that to animate the Advanced Marker, you should use CSS animation now to be able to do so as presented in their Advanced Marker sample here: https://developers.google.com/maps/documentation/javascript/examples/advanced-markers-animation

    With that said, to reproduce a somewhat similar bounce animation, you first need to define a .bounce(You can name this whatever you want) class inside your CSS using keyframes and transform:

    .bounce {
        animation: bounce 2s infinite;
        -webkit-animation: bounce 2s infinite;
        -moz-animation: bounce 2s infinite;
        -o-animation: bounce 2s infinite;
    }
     
    @-webkit-keyframes bounce {
        0%, 20%, 50%, 80%, 100% {-webkit-transform: translateY(0);} 
        40% {-webkit-transform: translateY(-30px);}
        60% {-webkit-transform: translateY(-15px);}
    }
     
    @-moz-keyframes bounce {
        0%, 20%, 50%, 80%, 100% {-moz-transform: translateY(0);}
        40% {-moz-transform: translateY(-30px);}
        60% {-moz-transform: translateY(-15px);}
    }
     
    @-o-keyframes bounce {
        0%, 20%, 50%, 80%, 100% {-o-transform: translateY(0);}
        40% {-o-transform: translateY(-30px);}
        60% {-o-transform: translateY(-15px);}
    }
    @keyframes bounce {
        0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
        40% {transform: translateY(-30px);}
        60% {transform: translateY(-15px);}
    }
    

    Then inside your map initialization function, you can just add the class .bounce to your marker element by using this code:

    marker.content.classList.add("bounce")
    

    Then the animation should work.

    Here's a proof of concept snippet for you to check:

    /**
     * @license
     * Copyright 2019 Google LLC. All Rights Reserved.
     * SPDX-License-Identifier: Apache-2.0
     */
    async function initMap() {
    
      // Request needed libraries.
      const { Map } = await google.maps.importLibrary("maps");
      const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
      // initialize the map
      const map = new Map(document.getElementById("map"), {
        center: { lat: 37.4239163, lng: -122.0947209 },
        zoom: 14,
        mapId: "4504f8b37365c3d0",
      });
      // initialize the marker
      const marker = new AdvancedMarkerElement({
        map,
        position: { lat: 37.4239163, lng: -122.0947209 },
      });
      // add the class "bounce" for your css configuration to apply
      marker.content.classList.add("bounce")
    }
    
    
    
    initMap();
    /**
     * @license
     * Copyright 2019 Google LLC. All Rights Reserved.
     * SPDX-License-Identifier: Apache-2.0
     */
    /* 
     * Always set the map height explicitly to define the size of the div element
     * that contains the map. 
     */
    #map {
      height: 100%;
    }
    
    /* 
     * Optional: Makes the sample page fill the window. 
     */
    html,
    body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    /* Define the bounce animation configuration here */
    .bounce {
        animation: bounce 2s infinite;
        -webkit-animation: bounce 2s infinite;
        -moz-animation: bounce 2s infinite;
        -o-animation: bounce 2s infinite;
    }
     
    @-webkit-keyframes bounce {
        0%, 20%, 50%, 80%, 100% {-webkit-transform: translateY(0);} 
        40% {-webkit-transform: translateY(-30px);}
        60% {-webkit-transform: translateY(-15px);}
    }
     
    @-moz-keyframes bounce {
        0%, 20%, 50%, 80%, 100% {-moz-transform: translateY(0);}
        40% {-moz-transform: translateY(-30px);}
        60% {-moz-transform: translateY(-15px);}
    }
     
    @-o-keyframes bounce {
        0%, 20%, 50%, 80%, 100% {-o-transform: translateY(0);}
        40% {-o-transform: translateY(-30px);}
        60% {-o-transform: translateY(-15px);}
    }
    @keyframes bounce {
        0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
        40% {transform: translateY(-30px);}
        60% {transform: translateY(-15px);}
    }
    <!doctype html>
    <!--
     @license
     Copyright 2019 Google LLC. All Rights Reserved.
     SPDX-License-Identifier: Apache-2.0
    -->
    <html>
      <head>
        <title>Default Advanced Marker</title>
        <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
        <!-- jsFiddle will insert css and js -->
      </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: "weekly"});</script>
      </body>
    </html>