إضافة تسمية توضيحية مخصّصة

نظرة عامة

تعرَّف على كيفية إنشاء تسمية توضيحية على خريطة Google من خلال هذا الدليل التوجيهي/التعليمي. تصف وسيلة الإيضاح بشكل عام الرموز والعلامات على الخريطة. يمكنك إنشاء هذه العناصر باستخدام ميزة تحديد الموضع في عناصر التحكّم المخصّصة.

تحتوي الخريطة أدناه على تسمية توضيحية تقدّم معلومات حول ثلاثة محدّدات مواقع مخصّصة مختلفة على الخريطة.

توضّح الأقسام أدناه الخطوات الرئيسية لإنشاء تسمية توضيحية.

يمكنك الاطّلاع على قسم مثال الرمز البرمجي الكامل للاطّلاع على الرمز الكامل.

إنشاء حاوية وسيلة الإيضاح

أنشِئ حاوية وسيلة الإيضاح من خلال إضافة 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 ديناميكيًا من حزمة تطوير البرامج (SDK) الخاصة بـ &quot;خرائط Google&quot; (await google.maps.importLibrary('marker')).
const { PinElement } = await google.maps.importLibrary('marker');
  1. إعداد الحاوية: يتم استرداد العنصر <div id="legend"> الفارغ الحالي من HTML وإضافة عنصر العنوان "مفتاح الخريطة" إليه.
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);
    }
}

اطّلِع على ميزات بيانات نقاط الأسلوب للاطّلاع على مثال آخر على وسيلة إيضاح تم إنشاؤها آليًا.

مثال على الرمز البرمجي الكامل

يعرض القسم أدناه الرمز الكامل الذي تحتاج إليه لإنشاء الخريطة ومفتاح الخريطة في هذا البرنامج التعليمي.

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>