Set collision behavior for a marker

  • This example demonstrates how to manage marker collisions on a map using the AdvancedMarkerElement and CollisionBehavior properties.

  • Users can interactively select different collision behaviors to control how markers overlap or hide each other.

  • The sample code utilizes the Google Maps JavaScript API with TypeScript and JavaScript examples provided.

  • The code dynamically creates and positions multiple markers on the map, showcasing the impact of the selected collision behavior.

  • A dropdown menu allows users to choose between various collision behaviors, dynamically updating the marker display.

This example shows setting collision behavior for a marker.

Read the documentation.

TypeScript

const mapElement = document.querySelector('gmp-map')!;

declare namespace mdc {
    namespace select {
        class MDCSelect {
            constructor(el: Element | null);
            listen(evtType: string, handler: (event: Event) => void): void;
            value: string;
        }
    }
}

// Initialize and add the map
async function init(): Promise<void> {
    // Request needed libraries.
    const [{ AdvancedMarkerElement }] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('maps'),
    ]);

    const markers: google.maps.marker.AdvancedMarkerElement[] = [];

    const collisionBehavior: google.maps.CollisionBehaviorString = 'REQUIRED';

    const select = new mdc.select.MDCSelect(
        document.querySelector('.mdc-select')
    );

    select.listen('MDCSelect:change', () => {
        markers.forEach((marker) => {
            marker.collisionBehavior =
                select.value as google.maps.CollisionBehavior;
        });
    });

    select.value = collisionBehavior;

    // Create some markers on the map
    const locations = [
        [-122.3402, 47.6093],
        [-122.3402, 47.6094],
        [-122.3403, 47.6094],
        [-122.3384, 47.6098],
        [-122.3389, 47.6095],
        [-122.3396, 47.6095],
        [-122.3379, 47.6097],
        [-122.3378, 47.6097],
        [-122.3396, 47.6091],
        [-122.3383, 47.6089],
        [-122.3379, 47.6093],
        [-122.3381, 47.6095],
        [-122.3378, 47.6095],
    ];

    locations.forEach(([lng, lat]: number[]) => {
        const advancedMarker = new AdvancedMarkerElement({
            position: { lat, lng },
            collisionBehavior,
        });
        mapElement.appendChild(advancedMarker);
        markers.push(advancedMarker);
    });
}

void init();

JavaScript

const mapElement = document.querySelector('gmp-map');

// Initialize and add the map
async function init() {
    // Request needed libraries.
    const [{ AdvancedMarkerElement }] = await Promise.all([
        google.maps.importLibrary('marker'),
        google.maps.importLibrary('maps'),
    ]);

    const markers = [];

    const collisionBehavior = 'REQUIRED';

    const select = new mdc.select.MDCSelect(
        document.querySelector('.mdc-select')
    );

    select.listen('MDCSelect:change', () => {
        markers.forEach((marker) => {
            marker.collisionBehavior = select.value;
        });
    });

    select.value = collisionBehavior;

    // Create some markers on the map
    const locations = [
        [-122.3402, 47.6093],
        [-122.3402, 47.6094],
        [-122.3403, 47.6094],
        [-122.3384, 47.6098],
        [-122.3389, 47.6095],
        [-122.3396, 47.6095],
        [-122.3379, 47.6097],
        [-122.3378, 47.6097],
        [-122.3396, 47.6091],
        [-122.3383, 47.6089],
        [-122.3379, 47.6093],
        [-122.3381, 47.6095],
        [-122.3378, 47.6095],
    ];

    locations.forEach(([lng, lat]) => {
        const advancedMarker = new AdvancedMarkerElement({
            position: { lat, lng },
            collisionBehavior,
        });
        mapElement.appendChild(advancedMarker);
        markers.push(advancedMarker);
    });
}

void init();

CSS

:root {
    --mdc-theme-primary: #1a73e8;
    --mdc-theme-secondary: #rgb(225, 245, 254);
    --mdc-theme-on-primary: #fff;
    --mdc-theme-on-secondary: rgb(1, 87, 155);
}

.mdc-text-field--focused:not(.mdc-text-field--disabled) .mdc-floating-label {
    color: var(--mdc-theme-primary);
}

.mdc-select--focused .mdc-select__dropdown-icon {
    background: url(data:image/svg+xml,%3Csvg%20width%3D%2210px%22%20height%3D%225px%22%20viewBox%3D%227%2010%2010%205%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%0A%20%20%20%20%3Cpolygon%20id%3D%22Shape%22%20stroke%3D%22none%22%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20opacity%3D%220.54%22%20points%3D%227%2010%2012%2015%2017%2010%22%3E%3C%2Fpolygon%3E%0A%3C%2Fsvg%3E)
        no-repeat center;
}

.mdc-select:not(.mdc-select--disabled).mdc-select--focused .mdc-floating-label {
    color: var(--mdc-theme-primary);
}

/* Optional: Makes the sample page fill the window. */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#container {
    height: 100%;
    display: flex;
}

#sidebar {
    flex-basis: 15rem;
    flex-grow: 1;
    padding: 1rem;
    max-width: 33rem;
    height: 100%;
    box-sizing: border-box;
    overflow: auto;
}

gmp-map {
    flex-basis: 0;
    flex-grow: 4;
    height: 100%;
}

.mdc-select,
.mdc-select__anchor,
.mdc-select__menu {
    width: 100%;
}

HTML

<html>
    <head>
        <title>Advanced Marker Collision Management</title>

        <link
            href="https://unpkg.com/material-components-web@6.0.0/dist/material-components-web.css"
            rel="stylesheet" />
        <script src="https://unpkg.com/material-components-web@6.0.0/dist/material-components-web.min.js"></script>
        <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/icon?family=Material+Icons" />

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <script>
            // prettier-ignore
            (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: "GOOGLE_MAPS_API_KEY"
            });
        </script>
    </head>
    <body>
        <div id="container">
            <gmp-map
                center="47.609414458375674,-122.33897030353548"
                zoom="17"
                map-id="6ff586e93e18149f"></gmp-map>
            <div id="sidebar">
                <div class="mdc-select mdc-select--outlined">
                    <div
                        class="mdc-select__anchor"
                        aria-labelledby="outlined-select-label">
                        <input
                            type="text"
                            disabled
                            readonly
                            id="demo-selected-text"
                            class="mdc-select__selected-text" />
                        <i class="mdc-select__dropdown-icon"></i>
                        <span class="mdc-notched-outline">
                            <span class="mdc-notched-outline__leading"></span>
                            <span class="mdc-notched-outline__notch">
                                <span
                                    id="outlined-select-label"
                                    class="mdc-floating-label mdc-theme--primary"
                                    >Pick a Collision Behavior</span
                                >
                            </span>
                            <span class="mdc-notched-outline__trailing"></span>
                        </span>
                    </div>
                    <div class="mdc-select__menu mdc-menu mdc-menu-surface">
                        <ul class="mdc-list">
                            <li class="mdc-list-item" data-value="REQUIRED">
                                Required
                            </li>
                            <li
                                class="mdc-list-item"
                                data-value="REQUIRED_AND_HIDES_OPTIONAL">
                                Required and hides optional
                            </li>
                            <li
                                class="mdc-list-item"
                                data-value="OPTIONAL_AND_HIDES_LOWER_PRIORITY">
                                Optional and hides lower priority
                            </li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

Clone Sample

Git and Node.js are required to run this sample locally. Follow these instructions to install Node.js and NPM. You will also need a Google Maps API key.

The following commands clone the repository, install dependencies, and copy the environment file.

  git clone https://github.com/googlemaps-samples/js-api-samples.git
  cd js-api-samples
  npm i
  cp .env.template .env

Once you copy the environment file, make sure to open the .env file and replace <Insert your own development API key here> with your actual API key before starting the sample.

  cd samples/advanced-markers-collision
  npm start