اضافه کردن یک افسانه سفارشی

نمای کلی

از طریق این آموزش یاد بگیرید که چگونه یک راهنما (legend) روی نقشه گوگل ایجاد کنید. راهنماها (legends) عموماً نمادها و نشانگرهای روی نقشه را توصیف می‌کنند. می‌توانید آنها را با استفاده از ویژگی موقعیت‌یابی کنترل‌های سفارشی (custom controls) ایجاد کنید.

نقشه زیر شامل توضیحاتی است که اطلاعاتی در مورد سه نشانگر سفارشی مختلف روی نقشه ارائه می‌دهد.

بخش‌های زیر مراحل اصلی ایجاد یک راهنما را توضیح می‌دهند.

برای مشاهده کد کامل به بخش نمونه کد کامل مراجعه کنید.

ایجاد کانتینر راهنما

با اضافه کردن یک div به عنصر gmp-map کانتینر راهنما را ایجاد کنید. از کنترل اسلاتینگ برای تنظیم موقعیت راهنما استفاده کنید. درباره گزینه‌های موقعیت کنترل بیشتر بخوانید.

<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>

برای تنظیم ظاهر بصری راهنما، سبک‌هایی را اعمال کنید. این مثال، به ظرف راهنما، عنوان و آیتم سبک می‌دهد.

#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;
}

محتوای راهنما را اضافه کنید

تابع makeLegend() به صورت برنامه‌نویسی شده یک راهنمای نقشه بصری می‌سازد و آن را در DOM صفحه درج می‌کند. نحوه کار آن به صورت زیر است:

  1. کتابخانه را وارد می‌کند: به صورت پویا کلاس PinElement را از Maps SDK وارد می‌کند ( await google.maps.importLibrary('marker') ).
const { PinElement } = await google.maps.importLibrary('marker');
  1. آماده‌سازی کانتینر: عنصر خالی <div id="legend"> موجود را از HTML می‌گیرد و یک عنصر عنوان "Legend" را به آن اضافه می‌کند.
const legend = document.getElementById('legend')!;

const title = document.createElement('div');
title.innerText = 'Legend';
title.classList.add('title');
legend.appendChild(title);
  1. تکرار روی پیکربندی‌ها: این تابع روی شیء پیکربندی icons حلقه می‌زند تا برای هر آیتم (پارکینگ، کتابخانه، اطلاعات) یک ردیف ایجاد کند. تابع کمکی به شکل زیر است:

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);
    }
}

برای مثال دیگری از یک راهنما که به صورت برنامه‌نویسی تولید شده است، به ویژگی‌های داده‌ی نقطه‌ی استایل مراجعه کنید.

مثال کد کامل

بخش زیر کل کدی را که برای ایجاد نقشه و راهنما در این آموزش نیاز دارید، نمایش می‌دهد.

تایپ اسکریپت

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();

جاوا اسکریپت

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();

سی اس اس

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>
    <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>