Nhóm điểm đánh dấu

Chọn nền tảng: Android iOS JavaScript

Tổng quan

Hướng dẫn này sẽ chỉ cho bạn cách sử dụng phân cụm điểm đánh dấu để hiển thị một số lượng lớn điểm đánh dấu trên bản đồ. Bạn có thể sử dụng thư viện @googlemaps/markerclusterer kết hợp với Maps JavaScript API để kết hợp các điểm đánh dấu ở gần nhau thành cụm và đơn giản hoá việc hiển thị điểm đánh dấu trên bản đồ.

Để xem cách hoạt động của tính năng phân cụm điểm đánh dấu, hãy xem bản đồ sau.

Số trên một cụm cho biết số lượng điểm đánh dấu mà cụm đó chứa. Xin lưu ý rằng khi bạn phóng to bất kỳ vị trí cụm nào, số trên cụm sẽ giảm và bạn bắt đầu thấy các điểm đánh dấu riêng lẻ trên bản đồ. Việc thu nhỏ bản đồ sẽ hợp nhất các điểm đánh dấu thành cụm một lần nữa.

Mẫu sau đây cho thấy mã hoàn chỉnh mà bạn cần để tạo bản đồ này.

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>

Để minh hoạ, hướng dẫn này sẽ thêm một nhóm điểm đánh dấu vào bản đồ bằng cách sử dụng mảng locations. Bạn có thể sử dụng các nguồn khác để lấy điểm đánh dấu cho bản đồ của mình. Để biết thêm thông tin, hãy đọc hướng dẫn tạo điểm đánh dấu.

Thêm trình tạo cụm điểm đánh dấu

Hãy làm theo các bước sau để thêm phân cụm điểm đánh dấu:

  1. Thêm thư viện phân cụm điểm đánh dấu vào trang hoặc ứng dụng của bạn. Thư viện này có trên NPM tại @googlemaps/markerclusterer và trong kho lưu trữ trên GitHub. Chọn một trong các tuỳ chọn sau để cài đặt thư viện:

    NPM

    Cài đặt thư viện @googlemaps/markerclusterer bằng NPM.

    npm install @googlemaps/markerclusterer

    CDN

    Tập lệnh sau đây tải thư viện từ CDN unpkg.com.

    <script src="https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js"></script>
  2. Thêm trình phân cụm điểm đánh dấu vào ứng dụng của bạn.

    Mã sau đây sẽ thêm trình tạo cụm điểm đánh dấu vào bản đồ. Chọn một trong các tuỳ chọn sau:

    NPM

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

    CDN

    Khi được truy cập bằng CDN, thư viện này sẽ có trong biến toàn cục markerClusterer.

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

    Mẫu này chuyển mảng markers đến MarkerClusterer.

  3. (Không bắt buộc) Tuỳ chỉnh phân cụm điểm đánh dấu để thay đổi giao diện biểu tượng cụm, thuật toán phân cụm hoặc hành vi nhấp.

Tuỳ chỉnh phân cụm điểm đánh dấu

Bạn có thể tuỳ chỉnh MarkerClusterer bằng cách chuyển các tuỳ chọn bổ sung trong MarkerClustererOptions đối tượng khi tạo thực thể trình tạo cụm:

  • renderer: Kiểm soát cách điểm đánh dấu cụm được kết xuất trên bản đồ.
  • algorithm và algorithmOptions: Kiểm soát cách các điểm đánh dấu được nhóm thành cụm dựa trên khoảng cách và mức thu phóng.
  • onClusterClick: Ghi đè hành vi mặc định khi người dùng nhấp vào điểm đánh dấu cụm.

Bản đồ sau đây cho thấy các điểm đánh dấu có biểu tượng cụm tuỳ chỉnh.

Tuỳ chỉnh biểu tượng cụm

Theo mặc định, MarkerClusterer sử dụng DefaultRenderer để tạo biểu tượng cụm SVG. Để tuỳ chỉnh giao diện của điểm đánh dấu cụm, hãy chuyển một đối tượng triển khai giao diện Renderer đến tuỳ chọn renderer.

Giao diện Renderer yêu cầu phương thức render(cluster, stats, map) trả về AdvancedMarkerElement (hoặc google.maps.Marker cũ). Phương thức render nhận các đối số sau:

  • cluster (Cluster): Biểu thị nhóm điểm đánh dấu, bao gồm:
    • count: Số điểm đánh dấu hiển thị trong cụm.
    • position: Vị trí trung tâm google.maps.LatLng của cụm.
    • bounds: google.maps.LatLngBounds của cụm.
    • markers: Mảng điểm đánh dấu có trong cụm.
  • stats (ClusterStats): Cung cấp số liệu thống kê trên tất cả các cụm trong chu kỳ kết xuất hiện tại, chẳng hạn như stats.clusters.markers.mean, min, max, và sum. Bạn có thể sử dụng các giá trị này để tạo kiểu cho cụm một cách linh động dựa trên kích thước tương đối của chúng.
  • map (google.maps.Map): Thực thể bản đồ.

Ví dụ sau đây xác định một renderer tuỳ chỉnh tạo huy hiệu HTML hình tròn cho mỗi AdvancedMarkerElement và thay đổi màu nền khi số lượng điểm đánh dấu cụm vượt quá kích thước cụm trung bình.

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

Xem ví dụ hoàn chỉnh về hiển thị tùy chỉnh

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>

Để xem thêm các ví dụ về trình kết xuất, hãy xem bản minh hoạ về cách sử dụng trình kết xuất .

Sửa đổi thuật toán tạo cụm

Theo mặc định, MarkerClusterer sử dụng SuperClusterAlgorithm, thuật toán này tạo cụm điểm đánh dấu bằng cách sử dụng cây k-d. Bạn có thể tuỳ chỉnh hành vi tạo cụm bằng cách chuyển một thực thể thuật toán đến tuỳ chọn algorithm hoặc bằng cách chuyển các tuỳ chọn cho thuật toán mặc định đến algorithmOptions.

Thư viện này bao gồm các thuật toán tích hợp sau:

  • SuperClusterAlgorithm (mặc định): Tạo cụm điểm địa lý nhanh chóng bằng cách sử dụng cây k-d. Các tuỳ chọn phổ biến bao gồm:
    • maxZoom: Mức thu phóng tối đa mà cụm được tạo (mặc định: 16). Ở các mức thu phóng trên maxZoom, các điểm đánh dấu riêng lẻ sẽ được hiển thị mà không cần tạo cụm.
    • radius: Bán kính cụm tính bằng pixel (mặc định: 60).
    • minPoints: Số điểm đánh dấu tối thiểu cần thiết để tạo thành một cụm (mặc định: 2).
  • SuperClusterViewportAlgorithm: Một biến thể được lọc theo khung hiển thị của SuperClusterAlgorithm chỉ tạo cụm điểm đánh dấu trong khung hiển thị bản đồ hiện tại cộng với phần đệm pixel (viewportPadding, mặc định: 60).
  • GridAlgorithm: Thuật toán tạo cụm dựa trên lưới. Các tuỳ chọn phổ biến bao gồm maxZoom (mặc định: 16), gridSize (kích thước lưới tính bằng pixel, mặc định: 40), và maxDistance (khoảng cách tối đa tính bằng mét giữa tâm cụm và điểm đánh dấu, mặc định: 40000).
  • NoopAlgorithm: Kết xuất tất cả các điểm đánh dấu mà không cần tạo cụm.

Ví dụ sau đây định cấu hình SuperClusterAlgorithm với radius và maxZoom tuỳ chỉnh:

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

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

Để so sánh cách hoạt động của các thuật toán khác nhau, hãy xem bản minh hoạ so sánh thuật toán .

Tuỳ chỉnh hành vi nhấp vào cụm

Theo mặc định, việc nhấp vào điểm đánh dấu cụm sẽ khớp khung hiển thị bản đồ với ranh giới của cụm đã nhấp (map.fitBounds(cluster.bounds)). Để tuỳ chỉnh những gì xảy ra khi người dùng nhấp vào một cụm, hãy truyền một hàm callback đến tuỳ chọn 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);
  },
});

Tìm hiểu thêm

Bạn có thể xem các ví dụ phức tạp hơn về tính năng tạo cụm điểm đánh dấu trong kho lưu trữ trên GitHub và đọc tài liệu tham khảo cho thư viện.