# Clusters

*Category:* Components
*Section:* Map
*Source:* https://uikit.developers.rio.cloud/#/components/mapCluster
*Captured:* 2026-04-27T14:58:50.599Z

## Clusters

### Example: Example 1

Terms of use © 1987–2026 HERE

50 km

Choose view
Map view
Satellite

Traffic conditions
Show traffic incidents

Regenerate data Toggle cluster

#### React (tsx)

```tsx
import { useState, useMemo } from 'react';

import Button from '@rio-cloud/rio-uikit/Button';
import Map from '@rio-cloud/rio-uikit/Map';
import MarkerLayer from '@rio-cloud/rio-uikit/MarkerLayer';
import EventUtils from '@rio-cloud/rio-uikit/EventUtils';
import MapSettings from '@rio-cloud/rio-uikit/MapSettings';
import MapTypeSettings from '@rio-cloud/rio-uikit/MapTypeSettings';
import MapClusterSettings from '@rio-cloud/rio-uikit/MapClusterSettings';
import SingleMapMarker from '@rio-cloud/rio-uikit/SingleMapMarker';
import ClusterMapMarker from '@rio-cloud/rio-uikit/ClusterMapMarker';
import type { MapEvent, Point } from '@rio-cloud/rio-uikit/mapTypes';

import { UIKIT_DEMO_CREDENTIALS_ARE_NOT_ALLOWED_IN_PROD_ENVIRONMENT } from '../uikit_demo_credentials';
import type { Asset } from '../settings/demoData';

const position = { lat: 49.1351, lng: 12.582 };
const NUM = 100;

const regenerateData = () =>
    Array.from({ length: NUM * 2 }, (_, index) => {
        const lat = position.lat + Math.random() * 6 - 3;
        const lng = position.lng + Math.random() * 10 - 5;
        return { lat, lng, data: `data-${index - NUM}`, name: `Asset ${index - NUM}`, type: 'truck' };
    });

const ClustersExample = () => {
    const [data, setData] = useState(regenerateData());
    const [showCluster, setShowCluster] = useState(true);

    const simpleTheme = useMemo(
        () => ({
            getNoisePresentation: ({ name, numberWarnings, numberExceptions, type }: Asset) => (
                <SingleMapMarker
                    iconNames={[type]}
                    name={name}
                    warningCount={numberWarnings}
                    exceptionCount={numberExceptions}
                />
            ),
            getClusterPresentation: (assets: Asset[]) => (
                <ClusterMapMarker
                    iconName='truck'
                    count={assets.length}
                    warningCount={Math.floor((assets.length * 10) / 3)}
                    exceptionCount={Math.floor((assets.length * 10) / 5)}
                />
            ),
        }),
        []
    );

    const handleClusterEvent = (event: MapEvent) => {
        const target = event.target.getData();
        event.stopPropagation();

        if (target.isCluster()) {
            console.log('cluster event:', event.type);
            target.forEachDataPoint((point: Point) => console.log(point.getData()));
        } else {
            console.log('noise point event:', event.type, target.getData());
        }
    };

    const handleToggleCluster = () => setShowCluster(!showCluster);

    const handleClusterChange = (newShowCluster: boolean) => setShowCluster(newShowCluster);

    const handleRegenerateDataButtonClick = () => {
        setData(regenerateData);
    };

    const eventListenerMap = EventUtils.createTapOnDblTapPreventer({
        [EventUtils.TAP]: handleClusterEvent,
        [EventUtils.DBL_TAP]: handleClusterEvent,
    });

    return (
        <>
            <Map
                credentials={UIKIT_DEMO_CREDENTIALS_ARE_NOT_ALLOWED_IN_PROD_ENVIRONMENT}
                center={position}
                zoom={8}
                height={400}
                showCluster={showCluster}
                onShowClusterChange={handleClusterChange}
                mapSettings={
                    <MapSettings
                        options={[
                            <MapTypeSettings
                                key='mapTypeSettings'
                                tooltip='Change map type'
                                dropdownHeaderText='Map views'
                                defaultTypeLabel='Default view'
                                truckTypeLabel='Truck view'
                                terrainTypeLabel='Terrain view'
                                satelliteTypeLabel='Satellite view'
                                nightTypeLabel='Night view'
                            />,
                            <MapClusterSettings
                                key='mapClusterSettings'
                                tooltip='Enable or disable marker cluster'
                                dropdownHeaderText='Vehicle cluster'
                                clusterEnabledLabel='Enable cluster'
                                clusterDisabledLabel='Disable cluster'
                            />,
                        ]}
                    />
                }
            >
                <MarkerLayer data={data} eventListenerMap={eventListenerMap} simpleTheme={simpleTheme} />
            </Map>
            <div className='btn-toolbar margin-top-10'>
                <Button onClick={handleRegenerateDataButtonClick}>Regenerate data</Button>
                <Button onClick={handleToggleCluster}>Toggle cluster</Button>
            </div>
        </>
    );
};

export default ClustersExample;
```

## Clusters with POIs

### Example: Example 2

Terms of use © 1987–2026 HERE

50 km

Choose view
Map view
Satellite

Traffic conditions
Show traffic incidents

Regenerate data

#### React (tsx)

```tsx
import { useState, useMemo } from 'react';

import Button from '@rio-cloud/rio-uikit/Button';
import Map from '@rio-cloud/rio-uikit/Map';
import MarkerLayer from '@rio-cloud/rio-uikit/MarkerLayer';
import EventUtils from '@rio-cloud/rio-uikit/EventUtils';
import MapSettings from '@rio-cloud/rio-uikit/MapSettings';
import MapTypeSettings from '@rio-cloud/rio-uikit/MapTypeSettings';
import SingleMapMarker from '@rio-cloud/rio-uikit/SingleMapMarker';
import ClusterMapMarker from '@rio-cloud/rio-uikit/ClusterMapMarker';
import type { MapEvent, Point } from '@rio-cloud/rio-uikit/mapTypes';

import { UIKIT_DEMO_CREDENTIALS_ARE_NOT_ALLOWED_IN_PROD_ENVIRONMENT } from '../uikit_demo_credentials';
import type { Asset } from '../settings/demoData';

const position = { lat: 49.1351, lng: 12.582 };
const NUM = 500;

type Poi = {
    data: string;
    name: string;
    type: string;
};

const regenerateAssetData = () =>
    Array.from({ length: NUM * 2 }, (_, index) => {
        const lat = position.lat + Math.random() * 6 - 3;
        const lng = position.lng + Math.random() * 10 - 5;
        return { lat, lng, data: `data-${index - NUM}`, name: `Asset ${index - NUM}`, type: 'truck' };
    });

const regeneratePoiData = () =>
    Array.from({ length: NUM * 2 }, (_, index) => {
        const lat = position.lat + Math.random() * 6 - 3;
        const lng = position.lng + Math.random() * 10 - 5;
        return { lat, lng, data: `data-${index - NUM}`, name: `Poi ${index - NUM}`, type: 'pushpin' };
    });

const ClustersExample = () => {
    const [assets, setAssets] = useState(regenerateAssetData());
    const [pois, setPois] = useState(regeneratePoiData());

    const assetTheme = useMemo(
        () => ({
            getNoisePresentation: ({ name, numberWarnings, numberExceptions, type }: Asset) => (
                <SingleMapMarker
                    iconNames={[type]}
                    name={name}
                    warningCount={numberWarnings}
                    exceptionCount={numberExceptions}
                />
            ),
            getClusterPresentation: ({ length }: Asset[]) => (
                <ClusterMapMarker
                    iconName='truck'
                    count={length}
                    warningCount={Math.floor((length * 10) / 3)}
                    exceptionCount={Math.floor((length * 10) / 5)}
                />
            ),
        }),
        []
    );

    const poiTheme = useMemo(
        () => ({
            getNoisePresentation: ({ name }: Poi) => (
                <SingleMapMarker iconNames={['pushpin']} name={name} markerColor='bg-map-marker-poi' />
            ),
            getClusterPresentation: ({ length }: Poi[]) => (
                <ClusterMapMarker iconName='pushpin' markerColor='bg-map-marker-poi' count={length} />
            ),
        }),
        []
    );

    const handleClusterEvent = (event: MapEvent) => {
        const target = event.target.getData();
        event.stopPropagation();

        if (target.isCluster()) {
            console.log('cluster event:', event.type);
            target.forEachDataPoint((point: Point) => console.log(point.getData()));
        } else {
            console.log('noise point event:', event.type, target.getData());
        }
    };

    const handleRegenerateDataButtonClick = () => {
        setAssets(regenerateAssetData);
        setPois(regeneratePoiData);
    };

    const eventListenerMap = EventUtils.createTapOnDblTapPreventer({
        [EventUtils.TAP]: handleClusterEvent,
        [EventUtils.DBL_TAP]: handleClusterEvent,
    });

    return (
        <>
            <Map
                credentials={UIKIT_DEMO_CREDENTIALS_ARE_NOT_ALLOWED_IN_PROD_ENVIRONMENT}
                center={position}
                zoom={8}
                height={400}
                mapSettings={
                    <MapSettings
                        options={[
                            <MapTypeSettings
                                key='mapTypeSettings'
                                tooltip='Change map type'
                                dropdownHeaderText='Map views'
                                defaultTypeLabel='Default view'
                                truckTypeLabel='Truck view'
                                terrainTypeLabel='Terrain view'
                                satelliteTypeLabel='Satellite view'
                                nightTypeLabel='Night view'
                            />,
                        ]}
                    />
                }
            >
                <MarkerLayer
                    data={pois}
                    simpleTheme={poiTheme}
                    clusterDissolvable={false}
                    eventListenerMap={eventListenerMap}
                />
                <MarkerLayer data={assets} simpleTheme={assetTheme} eventListenerMap={eventListenerMap} />
            </Map>
            <div className='btn-toolbar margin-top-10'>
                <Button onClick={handleRegenerateDataButtonClick}>Regenerate data</Button>
            </div>
        </>
    );
};

export default ClustersExample;
```