Benutzerdefinierte Legende hinzufügen

Übersicht

In diesem Tutorial erfahren Sie, wie Sie eine Legende auf einer Google Maps-Karte erstellen. In der Regel werden in Legenden die Symbole und Markierungen auf einer Karte erläutert. Sie können sie mithilfe der Positionierungsfunktion von benutzerdefinierten Steuerelementenerstellen.

Die Karte unten enthält eine Legende mit Informationen zu drei verschiedenen benutzerdefinierten Markierungen.

In den folgenden Abschnitten werden die wichtigsten Schritte zum Erstellen einer Legende erläutert.

Den Abschnitt Vollständiges Codebeispiel finden Sie im vollständigen Code.

Legendencontainer erstellen

Erstellen Sie den Legendencontainer, indem Sie dem gmp-map-Element ein div hinzufügen. Verwenden Sie die Steuerungspositionierung, um die Position der Legende festzulegen. Weitere Informationen zu den Optionen für die Positionierung von Steuerelementen.

<gmp-map center="-33.91722,151.23064" zoom="16.5" map-id="DEMO_MAP_ID">
    <div id="legend" slot="control-inline-start-block-start"></div>
</gmp-map>

Wenden Sie Stile an, um die visuelle Darstellung der Legende festzulegen. In diesem Beispiel werden der Legendencontainer, der Titel und das Element formatiert.

#legend {
    background-color: #fff;
    width: 15em;
    margin: 1em;
    border-radius: 8px;
    font-family: Roboto, Arial, sans-serif;
    overflow: hidden;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

.legend-item {
    margin: 0.5em 1em;
    display: flex;
    flex-direction: row;
    align-items: center;
    padding-bottom: 0.5em;
}

.legend-icon {
    margin-right: 1em;
    font-size: 24px;
}

.legend-text {
    font-size: 1.5em;
}

Legendeninhalt hinzufügen

Die Funktion makeLegend() erstellt programmatisch eine visuelle Kartenlegende und fügt sie in das DOM der Seite ein. So funktioniert's:

  1. Bibliothek importieren: Die Klasse PinElement wird dynamisch aus dem Maps SDK (await google.maps.importLibrary('marker')) importiert.
const { PinElement } = await google.maps.importLibrary('marker');
  1. Container vorbereiten:Das vorhandene leere <div id="legend"> wird aus dem HTML abgerufen und ein Titel-Element „Legende“ wird vorangestellt.
const legend = document.getElementById('legend')!;

const title = document.createElement('div');
title.innerText = 'Legend';
title.classList.add('title');
legend.appendChild(title);
  1. Konfigurationen durchlaufen:Das Konfigurationsobjekt icons wird durchlaufen, um für jedes Element (Parkplatz, Bibliothek, Info) eine Zeile zu generieren. Die Hilfsfunktion sieht so aus:

async function makeLegend() {
    const { PinElement } = await google.maps.importLibrary('marker');

    const legend = document.getElementById('legend');

    const title = document.createElement('div');
    title.innerText = 'Legend';
    title.classList.add('title');
    legend.appendChild(title);

    for (const type of Object.values(icons)) {
        const wrapper = document.createElement('div');
        wrapper.classList.add('legend-item');

        const pin = new PinElement({
            background: type.color,
            borderColor: type.color,
            glyphSrc: new URL(
                `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(type.icon)}`
            ),
            scale: 1.0,
        });

        // PinElement extends HTMLElement directly, so we can append it directly!
        const pinContainer = document.createElement('div');
        pinContainer.classList.add('legend-icon');
        pinContainer.appendChild(pin);

        const txt = document.createElement('div');
        txt.classList.add('legend-text');
        txt.innerText = type.name;

        wrapper.appendChild(pinContainer);
        wrapper.appendChild(txt);
        legend.appendChild(wrapper);
    }
}

Ein weiteres Beispiel für eine programmatisch generierte Legende finden Sie unter Punktdaten formatieren.

Vollständiges Codebeispiel

Der folgende Abschnitt enthält den gesamten Code, den Sie zum Erstellen der Karte und Legende in diesem Tutorial benötigen.

TypeScript

const parkingSvg = `<svg fill="white" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M13 3H6v18h4v-6h3c3.31 0 6-2.69 6-6s-2.69-6-6-6zm.2 8H10V7h3.2c1.1 0 2 .9 2 2s-.9 2-2 2z"/></svg>`;
const librarySvg = `<svg fill="white" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 11.55C9.64 9.35 6.48 8 3 8v11c3.48 0 6.64 1.35 9 3.55 2.36-2.19 5.52-3.55 9-3.55V8c-3.48 0-6.64 1.35-9 3.55zM12 8c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></svg>`;
const infoSvg = `<svg fill="white" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>`;

const icons: Record<string, { name: string; icon: string; color: string }> = {
    parking: {
        name: 'Parking',
        icon: parkingSvg,
        color: '#1E88E5', // Blue
    },
    library: {
        name: 'Library',
        icon: librarySvg,
        color: '#43A047', // Green
    },
    info: {
        name: 'Info',
        icon: infoSvg,
        color: '#E53935', // Red
    },
};

async function init(): Promise<void> {
    const [{ AdvancedMarkerElement, PinElement }, { event }] =
        await Promise.all([
            google.maps.importLibrary('marker'),
            google.maps.importLibrary('core'),
            google.maps.importLibrary('maps'),
        ]);

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

    // Wait for the map to load before building the legend.
    event.addListenerOnce(innerMap, 'idle', () => {
        void makeLegend();
    });

    const features = [
        {
            position: { lat: -33.91721, lng: 151.2263 },
            type: 'info',
        },
        {
            position: { lat: -33.91539, lng: 151.2282 },
            type: 'info',
        },
        {
            position: { lat: -33.91747, lng: 151.22912 },
            type: 'info',
        },
        {
            position: { lat: -33.9191, lng: 151.22907 },
            type: 'info',
        },
        {
            position: { lat: -33.91725, lng: 151.23011 },
            type: 'info',
        },
        {
            position: { lat: -33.91872, lng: 151.23089 },
            type: 'info',
        },
        {
            position: { lat: -33.91784, lng: 151.23094 },
            type: 'info',
        },
        {
            position: { lat: -33.91682, lng: 151.23149 },
            type: 'info',
        },
        {
            position: { lat: -33.9179, lng: 151.23463 },
            type: 'info',
        },
        {
            position: { lat: -33.91666, lng: 151.23468 },
            type: 'info',
        },
        {
            position: { lat: -33.916988, lng: 151.23364 },
            type: 'info',
        },
        {
            position: { lat: -33.91662347903106, lng: 151.22879464019775 },
            type: 'parking',
        },
        {
            position: { lat: -33.916365282092855, lng: 151.22937399734496 },
            type: 'parking',
        },
        {
            position: { lat: -33.91665018901448, lng: 151.2282474695587 },
            type: 'parking',
        },
        {
            position: { lat: -33.919543720969806, lng: 151.23112279762267 },
            type: 'parking',
        },
        {
            position: { lat: -33.91608037421864, lng: 151.23288232673644 },
            type: 'parking',
        },
        {
            position: { lat: -33.91851096391805, lng: 151.2344058214569 },
            type: 'parking',
        },
        {
            position: { lat: -33.91818154739766, lng: 151.2346203981781 },
            type: 'parking',
        },
        {
            position: { lat: -33.91727341958453, lng: 151.23348314155578 },
            type: 'library',
        },
    ];

    for (const feature of features) {
        const iconData = icons[feature.type];

        const pin = new PinElement({
            background: iconData.color,
            borderColor: iconData.color,
            glyphSrc: new URL(
                `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(iconData.icon)}`
            ),
            scale: 1.5,
        });

        const marker = new AdvancedMarkerElement({
            position: feature.position,
            title: iconData.name,
        });

        marker.append(pin);
        mapElement.append(marker);
    }
}

async function makeLegend() {
    const { PinElement } = await google.maps.importLibrary('marker');

    const legend = document.getElementById('legend')!;

    const title = document.createElement('div');
    title.innerText = 'Legend';
    title.classList.add('title');
    legend.appendChild(title);

    for (const type of Object.values(icons)) {
        const wrapper = document.createElement('div');
        wrapper.classList.add('legend-item');

        const pin = new PinElement({
            background: type.color,
            borderColor: type.color,
            glyphSrc: new URL(
                `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(type.icon)}`
            ),
            scale: 1.0,
        });

        // PinElement extends HTMLElement directly, so we can append it directly!
        const pinContainer = document.createElement('div');
        pinContainer.classList.add('legend-icon');
        pinContainer.appendChild(pin);

        const txt = document.createElement('div');
        txt.classList.add('legend-text');
        txt.innerText = type.name;

        wrapper.appendChild(pinContainer);
        wrapper.appendChild(txt);
        legend.appendChild(wrapper);
    }
}

void init();

JavaScript

const parkingSvg = `<svg fill="white" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M13 3H6v18h4v-6h3c3.31 0 6-2.69 6-6s-2.69-6-6-6zm.2 8H10V7h3.2c1.1 0 2 .9 2 2s-.9 2-2 2z"/></svg>`;
const librarySvg = `<svg fill="white" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 11.55C9.64 9.35 6.48 8 3 8v11c3.48 0 6.64 1.35 9 3.55 2.36-2.19 5.52-3.55 9-3.55V8c-3.48 0-6.64 1.35-9 3.55zM12 8c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></svg>`;
const infoSvg = `<svg fill="white" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></svg>`;

const icons = {
    parking: {
        name: 'Parking',
        icon: parkingSvg,
        color: '#1E88E5', // Blue
    },
    library: {
        name: 'Library',
        icon: librarySvg,
        color: '#43A047', // Green
    },
    info: {
        name: 'Info',
        icon: infoSvg,
        color: '#E53935', // Red
    },
};

async function init() {
    const [{ AdvancedMarkerElement, PinElement }, { event }] =
        await Promise.all([
            google.maps.importLibrary('marker'),
            google.maps.importLibrary('core'),
            google.maps.importLibrary('maps'),
        ]);

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

    // Wait for the map to load before building the legend.
    event.addListenerOnce(innerMap, 'idle', () => {
        void makeLegend();
    });

    const features = [
        {
            position: { lat: -33.91721, lng: 151.2263 },
            type: 'info',
        },
        {
            position: { lat: -33.91539, lng: 151.2282 },
            type: 'info',
        },
        {
            position: { lat: -33.91747, lng: 151.22912 },
            type: 'info',
        },
        {
            position: { lat: -33.9191, lng: 151.22907 },
            type: 'info',
        },
        {
            position: { lat: -33.91725, lng: 151.23011 },
            type: 'info',
        },
        {
            position: { lat: -33.91872, lng: 151.23089 },
            type: 'info',
        },
        {
            position: { lat: -33.91784, lng: 151.23094 },
            type: 'info',
        },
        {
            position: { lat: -33.91682, lng: 151.23149 },
            type: 'info',
        },
        {
            position: { lat: -33.9179, lng: 151.23463 },
            type: 'info',
        },
        {
            position: { lat: -33.91666, lng: 151.23468 },
            type: 'info',
        },
        {
            position: { lat: -33.916988, lng: 151.23364 },
            type: 'info',
        },
        {
            position: { lat: -33.91662347903106, lng: 151.22879464019775 },
            type: 'parking',
        },
        {
            position: { lat: -33.916365282092855, lng: 151.22937399734496 },
            type: 'parking',
        },
        {
            position: { lat: -33.91665018901448, lng: 151.2282474695587 },
            type: 'parking',
        },
        {
            position: { lat: -33.919543720969806, lng: 151.23112279762267 },
            type: 'parking',
        },
        {
            position: { lat: -33.91608037421864, lng: 151.23288232673644 },
            type: 'parking',
        },
        {
            position: { lat: -33.91851096391805, lng: 151.2344058214569 },
            type: 'parking',
        },
        {
            position: { lat: -33.91818154739766, lng: 151.2346203981781 },
            type: 'parking',
        },
        {
            position: { lat: -33.91727341958453, lng: 151.23348314155578 },
            type: 'library',
        },
    ];

    for (const feature of features) {
        const iconData = icons[feature.type];

        const pin = new PinElement({
            background: iconData.color,
            borderColor: iconData.color,
            glyphSrc: new URL(
                `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(iconData.icon)}`
            ),
            scale: 1.5,
        });

        const marker = new AdvancedMarkerElement({
            position: feature.position,
            title: iconData.name,
        });

        marker.append(pin);
        mapElement.append(marker);
    }
}

async function makeLegend() {
    const { PinElement } = await google.maps.importLibrary('marker');

    const legend = document.getElementById('legend');

    const title = document.createElement('div');
    title.innerText = 'Legend';
    title.classList.add('title');
    legend.appendChild(title);

    for (const type of Object.values(icons)) {
        const wrapper = document.createElement('div');
        wrapper.classList.add('legend-item');

        const pin = new PinElement({
            background: type.color,
            borderColor: type.color,
            glyphSrc: new URL(
                `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(type.icon)}`
            ),
            scale: 1.0,
        });

        // PinElement extends HTMLElement directly, so we can append it directly!
        const pinContainer = document.createElement('div');
        pinContainer.classList.add('legend-icon');
        pinContainer.appendChild(pin);

        const txt = document.createElement('div');
        txt.classList.add('legend-text');
        txt.innerText = type.name;

        wrapper.appendChild(pinContainer);
        wrapper.appendChild(txt);
        legend.appendChild(wrapper);
    }
}

void init();

CSS

html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

#legend {
    background-color: #fff;
    width: 15em;
    margin: 1em;
    border-radius: 8px;
    font-family: Roboto, Arial, sans-serif;
    overflow: hidden;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

.title {
    padding: 0.5em 1em;
    font-weight: bold;
    font-size: 1.5em;
    margin-bottom: 0.5em;
    background-color: rgb(66, 133, 244);
    color: white;
    box-sizing: border-box;
}

.legend-item {
    margin: 0.5em 1em;
    display: flex;
    flex-direction: row;
    align-items: center;
    padding-bottom: 0.5em;
}

.legend-icon {
    margin-right: 1em;
    font-size: 24px;
}

.legend-text {
    font-size: 1.5em;
}

HTML

<html>
    <head>
        <title>Custom Legend</title>

        <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>
        <gmp-map center="-33.91722,151.23064" zoom="16.5" map-id="DEMO_MAP_ID">
            <div id="legend" slot="control-inline-start-block-start"></div>
        </gmp-map>
    </body>
</html>