קיבוץ סמנים

בחירת פלטפורמה: Android iOS JavaScript

סקירה כללית

במדריך הזה מוסבר איך להשתמש במקבצי סמנים כדי להציג מספר גדול של סמנים במפה. אפשר להשתמש בספרייה ‎@googlemaps/markerclusterer בשילוב עם Maps JavaScript API כדי לשלב סמנים שקרובים זה לזה באשכולות, ולפשט את הצגת הסמנים במפה.

במפה הבאה אפשר לראות איך פועל קיבוץ הסמנים.

המספר שמופיע על אשכול מציין כמה סמנים הוא מכיל. שימו לב שככל שמתקרבים לאחד מהמיקומים של האשכול, המספר שמופיע על האשכול קטן ומתחילים לראות את הסמנים הנפרדים במפה. אם מקטינים את התצוגה של המפה, הסמנים מתאחדים שוב לקבוצות.

בדוגמה הבאה מוצג הקוד המלא שצריך כדי ליצור את המפה הזו.

TypeScript

import { MarkerClusterer } from '@googlemaps/markerclusterer';

async function init() {
    // Request needed libraries.
    const [{ InfoWindow }, { AdvancedMarkerElement, PinElement }] =
        await Promise.all([
            google.maps.importLibrary('maps'),
            google.maps.importLibrary('marker'),
        ]);

    const mapElement =
        document.querySelector<google.maps.MapElement>('gmp-map')!;
    const innerMap = mapElement.innerMap;

    const infoWindow = new InfoWindow({
        content: '',
        disableAutoPan: true,
    });

    // Create an array of alphabetical characters used to label the markers.
    const labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    // Add some markers to the map.
    const markers = locations.map((position, i) => {
        const label = labels[i % labels.length];
        const pinGlyph = new PinElement({
            glyphText: label,
            glyphColor: 'white',
        });

        const marker = new AdvancedMarkerElement({
            position,
            content: pinGlyph,
            gmpClickable: true,
        });

        // markers can only be keyboard focusable when they have click listeners
        // open info window when marker is clicked
        marker.addEventListener('gmp-click', () => {
            const content = document.createElement('div');
            content.textContent = `${String(position.lat)}, ${String(position.lng)}`;
            infoWindow.setContent(content);

            infoWindow.open({
                anchor: marker,
                map: innerMap,
            });
        });
        return marker;
    });

    // Add a marker clusterer to manage the markers.
    new MarkerClusterer({ markers, map: innerMap });
}

const locations = [
    { lat: -31.56391, lng: 147.154312 },
    { lat: -33.718234, lng: 150.363181 },
    { lat: -33.727111, lng: 150.371124 },
    { lat: -33.848588, lng: 151.209834 },
    { lat: -33.851702, lng: 151.216968 },
    { lat: -34.671264, lng: 150.863657 },
    { lat: -35.304724, lng: 148.662905 },
    { lat: -36.817685, lng: 175.699196 },
    { lat: -36.828611, lng: 175.790222 },
    { lat: -37.75, lng: 145.116667 },
    { lat: -37.759859, lng: 145.128708 },
    { lat: -37.765015, lng: 145.133858 },
    { lat: -37.770104, lng: 145.143299 },
    { lat: -37.7737, lng: 145.145187 },
    { lat: -37.774785, lng: 145.137978 },
    { lat: -37.819616, lng: 144.968119 },
    { lat: -38.330766, lng: 144.695692 },
    { lat: -39.927193, lng: 175.053218 },
    { lat: -41.330162, lng: 174.865694 },
    { lat: -42.734358, lng: 147.439506 },
    { lat: -42.734358, lng: 147.501315 },
    { lat: -42.735258, lng: 147.438 },
    { lat: -43.999792, lng: 170.463352 },
];

void init();

JavaScript

import { MarkerClusterer } from '@googlemaps/markerclusterer';

async function init() {
    // Request needed libraries.
    const [{ InfoWindow }, { AdvancedMarkerElement, PinElement }] =
        await Promise.all([
            google.maps.importLibrary('maps'),
            google.maps.importLibrary('marker'),
        ]);

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

    const infoWindow = new InfoWindow({
        content: '',
        disableAutoPan: true,
    });

    // Create an array of alphabetical characters used to label the markers.
    const labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    // Add some markers to the map.
    const markers = locations.map((position, i) => {
        const label = labels[i % labels.length];
        const pinGlyph = new PinElement({
            glyphText: label,
            glyphColor: 'white',
        });

        const marker = new AdvancedMarkerElement({
            position,
            content: pinGlyph,
            gmpClickable: true,
        });

        // markers can only be keyboard focusable when they have click listeners
        // open info window when marker is clicked
        marker.addEventListener('gmp-click', () => {
            const content = document.createElement('div');
            content.textContent = `${String(position.lat)}, ${String(position.lng)}`;
            infoWindow.setContent(content);

            infoWindow.open({
                anchor: marker,
                map: innerMap,
            });
        });
        return marker;
    });

    // Add a marker clusterer to manage the markers.
    new MarkerClusterer({ markers, map: innerMap });
}

const locations = [
    { lat: -31.56391, lng: 147.154312 },
    { lat: -33.718234, lng: 150.363181 },
    { lat: -33.727111, lng: 150.371124 },
    { lat: -33.848588, lng: 151.209834 },
    { lat: -33.851702, lng: 151.216968 },
    { lat: -34.671264, lng: 150.863657 },
    { lat: -35.304724, lng: 148.662905 },
    { lat: -36.817685, lng: 175.699196 },
    { lat: -36.828611, lng: 175.790222 },
    { lat: -37.75, lng: 145.116667 },
    { lat: -37.759859, lng: 145.128708 },
    { lat: -37.765015, lng: 145.133858 },
    { lat: -37.770104, lng: 145.143299 },
    { lat: -37.7737, lng: 145.145187 },
    { lat: -37.774785, lng: 145.137978 },
    { lat: -37.819616, lng: 144.968119 },
    { lat: -38.330766, lng: 144.695692 },
    { lat: -39.927193, lng: 175.053218 },
    { lat: -41.330162, lng: 174.865694 },
    { lat: -42.734358, lng: 147.439506 },
    { lat: -42.734358, lng: 147.501315 },
    { lat: -42.735258, lng: 147.438 },
    { lat: -43.999792, lng: 170.463352 },
];

void init();

CSS

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

HTML

<html>
    <head>
        <title>Marker Clustering</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="-28.024,140.887"
            zoom="3"
            map-id="DEMO_MAP_ID"></gmp-map>
    </body>
</html>

לשם המחשה, במדריך הזה מוסיפים קבוצה של סמנים למפה באמצעות המערך locations. אתם יכולים להשתמש במקורות אחרים כדי לקבל סמנים למפה. מידע נוסף זמין במדריך בנושא יצירת סמנים.

הוספת מקבץ סמנים

כדי להוסיף כלי לאיגוד סמנים:

  1. מוסיפים את ספריית מקבצי הסמנים לדף או לאפליקציה. הספרייה זמינה ב-NPM בכתובת ‎@googlemaps/markerclusterer ובמאגר ב-GitHub. בוחרים באחת מהאפשרויות הבאות כדי להתקין את הספרייה:

    NPM

    מתקינים את הספרייה @googlemaps/markerclusterer באמצעות NPM.

    npm install @googlemaps/markerclusterer

    CDN

    הסקריפט הבא טוען את הספרייה מ-unpkg.com CDN.

    <script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>
  2. מוסיפים מקבץ סמנים באפליקציה.

    הקוד הבא מוסיף למפה מקבץ סמנים. בוחרים באחת מהאפשרויות הבאות:

    NPM

    import { MarkerClusterer } from "@googlemaps/markerclusterer";
    
    const markerCluster = new MarkerClusterer({ markers, map });

    CDN

    כשניגשים לספרייה באמצעות ה-CDN, היא זמינה בקטע markerClusterer global.

    const markerCluster = new markerClusterer.MarkerClusterer({ markers, map });

    בדוגמה הזו, המערך markers מועבר אל MarkerClusterer.

  3. (אופציונלי) מתאימים אישית את מקבץ הסמנים כדי לשנות את המראה של סמל המקבץ, את אלגוריתם הקיבוץ או את אופן הפעולה של הקליק.

התאמה אישית של מקבץ סמנים

אפשר להתאים אישית את MarkerClusterer על ידי העברת אפשרויות נוספות באובייקט MarkerClustererOptions כשיוצרים את המכונה של האשכול:

  • ‫renderer: קובעת איך סמני האשכול מוצגים במפה.
  • ‫algorithm ו-algorithmOptions: קובעים איך הסמנים מקובצים לאשכולות על סמך המרחק ורמת הזום.
  • ‫onClusterClick: מבטל את התנהגות ברירת המחדל כשמשתמש לוחץ על סמן של אשכול.

במפה הבאה מוצגים סמנים עם סמלי אשכולות בהתאמה אישית.

התאמה אישית של סמל האשכול

כברירת מחדל, MarkerClusterer משתמש ב-DefaultRenderer כדי ליצור סמלי אשכולות מסוג SVG. כדי להתאים אישית את המראה של סמני האשכולות, מעבירים אובייקט שמטמיע את הממשק Renderer לאפשרות renderer.

הממשק Renderer דורש שיטה render(cluster, stats, map) שמחזירה AdvancedMarkerElement (או google.maps.Marker מדור קודם). השיטה render מקבלת את הארגומנטים הבאים:

  • ‫cluster (Cluster): מייצג את קבוצת הסמנים, כולל:
    • ‫count: מספר הסמנים הגלויים באשכול.
    • ‫position: המיקום המרכזי של האשכול ב-google.maps.LatLng.
    • ‫bounds: ה-google.maps.LatLngBounds של האשכול.
    • ‫markers: מערך הסמנים שכלולים באשכול.
  • ‫stats (ClusterStats): מספק נתונים סטטיסטיים לגבי כל האשכולות במחזור העיבוד הנוכחי, כמו stats.clusters.markers.mean,‏ min,‏ max ו-sum. אתם יכולים להשתמש בערכים האלה כדי לעצב אשכולות באופן דינמי על סמך הגודל היחסי שלהם.
  • ‫map (google.maps.Map): מופע המפה.

בדוגמה הבאה מוגדר renderer בהתאמה אישית שיוצר תג HTML עגול לכל AdvancedMarkerElement ומשנה את צבע הרקע שלו כשמספר הסמנים באשכול חורג מהגודל הממוצע של האשכול.

TypeScript

// Customize the cluster icons using a custom Renderer
    const renderer = {
        render: (
            {
                count,
                position,
            }: { count: number; position: google.maps.LatLng },
            stats: ClusterStats
        ) => {
            // Change color based on the number of markers in the cluster relative to the mean
            const isLargeCluster =
                count > Math.max(10, stats.clusters.markers.mean);
            const clusterClass = isLargeCluster
                ? 'large-cluster'
                : 'small-cluster';

            // Build the HTML content for the Advanced Marker
            const content = document.createElement('div');
            content.classList.add('custom-cluster-icon', clusterClass);
            content.textContent = String(count);

            return new AdvancedMarkerElement({
                position,
                content,
                // Adjust zIndex to be above other markers
                zIndex: 1000 + count,
            });
        },
    };

    // Add a marker clusterer to manage the markers.
    new MarkerClusterer({ markers, map: innerMap, renderer });
}

JavaScript

// Customize the cluster icons using a custom Renderer
    const renderer = {
        render: ({ count, position }, stats) => {
            // Change color based on the number of markers in the cluster relative to the mean
            const isLargeCluster =
                count > Math.max(10, stats.clusters.markers.mean);
            const clusterClass = isLargeCluster
                ? 'large-cluster'
                : 'small-cluster';

            // Build the HTML content for the Advanced Marker
            const content = document.createElement('div');
            content.classList.add('custom-cluster-icon', clusterClass);
            content.textContent = String(count);

            return new AdvancedMarkerElement({
                position,
                content,
                // Adjust zIndex to be above other markers
                zIndex: 1000 + count,
            });
        },
    };

    // Add a marker clusterer to manage the markers.
    new MarkerClusterer({ markers, map: innerMap, renderer });
}

דוגמה מלאה של רכיב רינדור בהתאמה אישית

TypeScript

import { MarkerClusterer, ClusterStats } from '@googlemaps/markerclusterer';

async function init() {
    // Request needed libraries.
    const [{ InfoWindow }, { AdvancedMarkerElement, PinElement }] =
        await Promise.all([
            google.maps.importLibrary('maps'),
            google.maps.importLibrary('marker'),
        ]);

    await customElements.whenDefined('gmp-map');

    const mapElement =
        document.querySelector<google.maps.MapElement>('gmp-map')!;
    const innerMap = mapElement.innerMap;

    const infoWindow = new InfoWindow({
        content: '',
        disableAutoPan: true,
    });

    // Create an array of alphabetical characters used to label the markers.
    const labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    // Add some markers to the map.
    const markers = locations.map((position, i) => {
        const label = labels[i % labels.length];
        const pinGlyph = new PinElement({
            glyphText: label,
            glyphColor: 'white',
        });

        const marker = new AdvancedMarkerElement({
            position,
            content: pinGlyph,
            gmpClickable: true,
        });

        marker.addEventListener('gmp-click', () => {
            const content = document.createElement('div');
            content.textContent = `${String(position.lat)}, ${String(position.lng)}`;
            infoWindow.setContent(content);

            infoWindow.open({
                anchor: marker,
                map: innerMap,
            });
        });
        return marker;
    });

    // Customize the cluster icons using a custom Renderer
    const renderer = {
        render: (
            {
                count,
                position,
            }: { count: number; position: google.maps.LatLng },
            stats: ClusterStats
        ) => {
            // Change color based on the number of markers in the cluster relative to the mean
            const isLargeCluster =
                count > Math.max(10, stats.clusters.markers.mean);
            const clusterClass = isLargeCluster
                ? 'large-cluster'
                : 'small-cluster';

            // Build the HTML content for the Advanced Marker
            const content = document.createElement('div');
            content.classList.add('custom-cluster-icon', clusterClass);
            content.textContent = String(count);

            return new AdvancedMarkerElement({
                position,
                content,
                // Adjust zIndex to be above other markers
                zIndex: 1000 + count,
            });
        },
    };

    // Add a marker clusterer to manage the markers.
    new MarkerClusterer({ markers, map: innerMap, renderer });
}

const locations = [
    { lat: -31.56391, lng: 147.154312 },
    { lat: -33.718234, lng: 150.363181 },
    { lat: -33.727111, lng: 150.371124 },
    { lat: -33.848588, lng: 151.209834 },
    { lat: -33.851702, lng: 151.216968 },
    { lat: -34.671264, lng: 150.863657 },
    { lat: -35.304724, lng: 148.662905 },
    { lat: -36.817685, lng: 175.699196 },
    { lat: -36.828611, lng: 175.790222 },
    { lat: -37.75, lng: 145.116667 },
    { lat: -37.759859, lng: 145.128708 },
    { lat: -37.765015, lng: 145.133858 },
    { lat: -37.770104, lng: 145.143299 },
    { lat: -37.7737, lng: 145.145187 },
    { lat: -37.774785, lng: 145.137978 },
    { lat: -37.819616, lng: 144.968119 },
    { lat: -38.330766, lng: 144.695692 },
    { lat: -39.927193, lng: 175.053218 },
    { lat: -41.330162, lng: 174.865694 },
    { lat: -42.734358, lng: 147.439506 },
    { lat: -42.734358, lng: 147.501315 },
    { lat: -42.735258, lng: 147.438 },
    { lat: -43.999792, lng: 170.463352 },
];

void init();

JavaScript

import { MarkerClusterer } from '@googlemaps/markerclusterer';

async function init() {
    // Request needed libraries.
    const [{ InfoWindow }, { AdvancedMarkerElement, PinElement }] =
        await Promise.all([
            google.maps.importLibrary('maps'),
            google.maps.importLibrary('marker'),
        ]);

    await customElements.whenDefined('gmp-map');

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

    const infoWindow = new InfoWindow({
        content: '',
        disableAutoPan: true,
    });

    // Create an array of alphabetical characters used to label the markers.
    const labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';

    // Add some markers to the map.
    const markers = locations.map((position, i) => {
        const label = labels[i % labels.length];
        const pinGlyph = new PinElement({
            glyphText: label,
            glyphColor: 'white',
        });

        const marker = new AdvancedMarkerElement({
            position,
            content: pinGlyph,
            gmpClickable: true,
        });

        marker.addEventListener('gmp-click', () => {
            const content = document.createElement('div');
            content.textContent = `${String(position.lat)}, ${String(position.lng)}`;
            infoWindow.setContent(content);

            infoWindow.open({
                anchor: marker,
                map: innerMap,
            });
        });
        return marker;
    });

    // Customize the cluster icons using a custom Renderer
    const renderer = {
        render: ({ count, position }, stats) => {
            // Change color based on the number of markers in the cluster relative to the mean
            const isLargeCluster =
                count > Math.max(10, stats.clusters.markers.mean);
            const clusterClass = isLargeCluster
                ? 'large-cluster'
                : 'small-cluster';

            // Build the HTML content for the Advanced Marker
            const content = document.createElement('div');
            content.classList.add('custom-cluster-icon', clusterClass);
            content.textContent = String(count);

            return new AdvancedMarkerElement({
                position,
                content,
                // Adjust zIndex to be above other markers
                zIndex: 1000 + count,
            });
        },
    };

    // Add a marker clusterer to manage the markers.
    new MarkerClusterer({ markers, map: innerMap, renderer });
}

const locations = [
    { lat: -31.56391, lng: 147.154312 },
    { lat: -33.718234, lng: 150.363181 },
    { lat: -33.727111, lng: 150.371124 },
    { lat: -33.848588, lng: 151.209834 },
    { lat: -33.851702, lng: 151.216968 },
    { lat: -34.671264, lng: 150.863657 },
    { lat: -35.304724, lng: 148.662905 },
    { lat: -36.817685, lng: 175.699196 },
    { lat: -36.828611, lng: 175.790222 },
    { lat: -37.75, lng: 145.116667 },
    { lat: -37.759859, lng: 145.128708 },
    { lat: -37.765015, lng: 145.133858 },
    { lat: -37.770104, lng: 145.143299 },
    { lat: -37.7737, lng: 145.145187 },
    { lat: -37.774785, lng: 145.137978 },
    { lat: -37.819616, lng: 144.968119 },
    { lat: -38.330766, lng: 144.695692 },
    { lat: -39.927193, lng: 175.053218 },
    { lat: -41.330162, lng: 174.865694 },
    { lat: -42.734358, lng: 147.439506 },
    { lat: -42.734358, lng: 147.501315 },
    { lat: -42.735258, lng: 147.438 },
    { lat: -43.999792, lng: 170.463352 },
];

void init();

CSS

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

.custom-cluster-icon {
    width: 45px;
    height: 45px;
    border-radius: 50%;
    border: 2px solid white;
    display: flex;
    justify-content: center;
    align-items: center;
    color: white;
    font-weight: bold;
    font-size: 14px;
    font-family: sans-serif;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

.large-cluster {
    background-color: #ff0000;
}

.small-cluster {
    background-color: #0000ff;
}

HTML

<html>
    <head>
        <title>marker-clustering-custom</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="-28.024, 140.887"
            zoom="3"
            map-id="DEMO_MAP_ID"></gmp-map>
    </body>
</html>

דוגמאות נוספות לשימוש ברכיב ה-renderer מופיעות בהדגמה של השימוש ברכיב ה-renderer.

שינוי אלגוריתם האשכולות

כברירת מחדל, MarkerClusterer משתמש ב-SuperClusterAlgorithm, שיוצר אשכולות של סמנים באמצעות עצי k-d. אפשר להתאים אישית את התנהגות האשכולות על ידי העברת מופע של אלגוריתם לאפשרות algorithm, או על ידי העברת אפשרויות לאלגוריתם ברירת המחדל לאפשרות algorithmOptions.

הספרייה כוללת את האלגוריתמים המובנים הבאים:

  • ‫SuperClusterAlgorithm (ברירת מחדל): אשכולות מהירים של נקודות גיאו-מרחביות באמצעות עצים k-d. אפשרויות נפוצות:
    • ‫maxZoom: רמת הזום המקסימלית שבה נוצרים אשכולות (ברירת המחדל: 16). ברמות זום שגבוהות מ-maxZoom, סמנים בודדים מוצגים בלי אשכולות.
    • ‫radius: רדיוס האשכול בפיקסלים (ברירת המחדל: 60).
    • ‫minPoints: המספר המינימלי של סמנים שנדרשים כדי ליצור אשכול (ברירת המחדל: 2).
  • SuperClusterViewportAlgorithm: גרסה של SuperClusterAlgorithm עם סינון לפי אזור תצוגה, שיוצרת אשכולות של סמנים רק בתוך אזור התצוגה הנוכחי של המפה, בתוספת מרווח פנימי בפיקסלים (viewportPadding, ברירת המחדל: 60).
  • ‫GridAlgorithm: אלגוריתם אשכולות מבוסס-רשת. האפשרויות הנפוצות כוללות את maxZoom (ברירת המחדל: 16), gridSize (גודל הרשת בפיקסלים, ברירת המחדל: 40) ו- maxDistance (המרחק המקסימלי במטרים בין מרכז האשכול לסמן, ברירת המחדל: 40000).
  • ‫NoopAlgorithm: רינדור של כל הסמנים בלי לקבץ אותם.

בדוגמה הבאה מגדירים את SuperClusterAlgorithm עם radius ו-maxZoom בהתאמה אישית:

import {MarkerClusterer, SuperClusterAlgorithm} from '@googlemaps/markerclusterer';

const markerCluster = new MarkerClusterer({
  map,
  markers,
  algorithm: new SuperClusterAlgorithm({
    radius: 80,
    maxZoom: 15,
  }),
});

כדי להשוות בין התנהגות האלגוריתמים השונים, אפשר לעיין בהדגמה של השוואה בין אלגוריתמים.

התאמה אישית של התנהגות הקליקים על אשכולות

כברירת מחדל, כשלוחצים על סמן של אשכול, אזור התצוגה של המפה מותאם לגבולות של האשכול שעליו לחצו (map.fitBounds(cluster.bounds)). כדי להתאים אישית את מה שקורה כשמשתמש לוחץ על אשכול, מעבירים פונקציית קריאה חוזרת לאפשרות onClusterClick:

const markerCluster = new MarkerClusterer({
  map,
  markers,
  onClusterClick: (event, cluster, map) => {
    // Zoom in by 2 levels centered on the cluster position
    map.setCenter(cluster.position);
    map.setZoom((map.getZoom() ?? 3) + 2);
  },
});

מידע נוסף

אתם יכולים לראות דוגמאות מורכבות יותר של קיבוץ סמנים במאגר ב-GitHub ולקרוא את מאמרי העזרה של הספרייה.