MMapClusterer

The MMapClusterer class is used to display a large number of markers on the map.
Zooming out of the map combines individual markers into a cluster. Zooming in breaks the cluster into individual markers.

Note

This class is a JS API package component and provides additional features not included in the core API.

To integrate the package, follow the instructions.

Usage example

Creating a map and adding a cluster to the map

Declare a variable for Map, load the mappable library, and extract the necessary classes.

window.map = null;
async function main() {
  await mappable.ready;

  const {MMap, MMapDefaultSchemeLayer, MMapMarker, MMapLayer, MMapFeatureDataSource} = mappable;
  //...
}

Load the package with the cluster, extract the classes for creating clusterized objects and the clusterization method.

const {MMapClusterer, clusterByGrid} = await mappable.import('@mappable-world/mappable-clusterer');

Create a layer with a default scheme, data sources, and a marker layer and add it to the map.

map = new MMap(document.getElementById('app'), {location: {center: [37.62, 55.62], zoom: 10}});
map
  .addChild(new MMapDefaultSchemeLayer())
  .addChild(new MMapFeatureDataSource({id: 'my-source'}))
  .addChild(new MMapLayer({source: 'my-source', type: 'markers', zIndex: 1800}));

You can set any layout for the marker and the cluster.

const contentPin = document.createElement('div');
contentPin.innerHTML = '<img src="./pin.svg" />';

Declare a function for rendering regular markers and submit it to the cluster settings.
Please note that the function must return any Entity element. In the example, this is mappable. Map marker.

const marker = (feature) =>
  new mappable.MMapMarker(
    {
      coordinates: feature.geometry.coordinates,
      source: 'my-source'
    },
    contentPin.cloneNode(true)
  );

As for regular markers, declare a cluster rendering function that also returns an entity element.

const cluster = (coordinates, features) =>
  new mappable.MMapMarker(
    {
      coordinates,
      source: 'my-source'
    },
    circle(features.length).cloneNode(true)
  );

function circle(count) {
  const circle = document.createElement('div');
  circle.classList.add('circle');
  circle.innerHTML = `
        <div class="circle-content">
            <span class="circle-text">${count}</span>
        </div>
    `;
  return circle;
}

Declare an array with the coordinates of markers and then create an array of objects with the appropriate interface. Pass it to the cluster settings.

const coordinates = [
  [37.64, 55.76],
  [37.63, 55.7],
  [37.43, 55.69],
  [37.47, 55.68],
  [38.53, 58.6],
  [37.59, 55.71],
  [37.5, 55.63],
  [37.52, 55.57],
  [37.52, 58.57],
  [40.52, 58.57]
];

const points = coordinates.map((lnglat, i) => ({
  type: 'Feature',
  id: i,
  geometry: {coordinates: lnglat},
  properties: {name: 'Point of issue of orders'}
}));

Create a cluster object and add it to the map object.
Pass a clusterization method, an array of objects, and marker and cluster rendering functions as parameters.
For the clusterization method, pass the grid division size in pixels.

const clusterer = new MMapClusterer({
        method: clusterByGrid({gridSize: 64}),
        features: points,
        marker,
        cluster
    });

    map.addChild(clusterer);
}

Using a cluster with React JS

Declare a variable for Map, load the mappable library, and extract the necessary classes.

window.map = null;
main();
async function main() {
    await mappable.ready;
    const mappableReact = await mappable.import('@mappable-world/mappable-reactify');
    const reactify = mappableReact.reactify.bindTo(React, ReactDOM);
    const {
        MMap,
        MMapDefaultSchemeLayer,
        MMapLayer,
        MMapFeatureDataSource,
        MMapMarker
    } = reactify.module(mappable);

Connect the package with the cluster, extract the classes for creating clusterized objects and the clusterization method.

const {MMapClusterer, clusterByGrid} = reactify.module(await mappable.import('@mappable-world/mappable-clusterer@0.0.1'));

Extract the hooks. Declare an array with the coordinates of markers and then create an array of objects with the appropriate interface.
Pass it to the cluster settings.

const {useCallback, useMemo} = React;

const coordinates = [
  [37.64, 55.76],
  [37.63, 55.7],
  [37.43, 55.69],
  [37.47, 55.68],
  [38.53, 58.6],
  [37.59, 55.71],
  [37.5, 55.63],
  [37.52, 55.57],
  [37.52, 58.57],
  [40.52, 58.57]
];

const points = coordinates.map((lnglat, i) => ({
  type: 'Feature',
  id: i,
  geometry: {coordinates: lnglat},
  properties: {name: 'Point of issue of orders'}
}));

Declare a rendering function. For the clusterization method, pass and save the grid division size in pixels.

function App() {
  const gridSizedMethod = useMemo(() => clusterByGrid({ gridSize: 64 }), []);
  // ...
}

Declare a function for displaying regular markers. Please note that the function must return any Entity element. In the example, this is mappable.Map marker.

const marker = useCallback(
  (feature) => (
    <MMapMarker coordinates={feature.geometry.coordinates} source={'my-source'}>
      <img src={'./pin.svg'} />
    </MMapMarker>
  ),
  []
);

Declare a cluster rendering function that also returns an entity element. Pass marker and cluster rendering functions to the cluster settings.

const cluster = useCallback(
  (coordinates, features) => (
    <MMapMarker coordinates={coordinates} source={'my-source'}>
      <div className="circle">
        <div className="circle-content">
          <span className="circle-text">{features.length}</span>
        </div>
      </div>
    </MMapMarker>
  ),
  []
);

Return a JSX element where we visualize the map components, default layer, data sources, marker layer, and clusterer.
In cluster props, pass the previously declared marker and cluster rendering functions, a clusterization method, and an array of objects.

return <React.Fragment>
    <MMap location={LOCATION} ref={x => map = x}>
        <MMapDefaultSchemeLayer />
        <MMapFeatureDataSource id="my-source"/>
        <MMapLayer source="my-source" type="markers" zIndex={1800}/>
        <MMapClusterer
            marker={marker}
            cluster={cluster}
            method={gridSizedMethod}
            features={points}
        />
    </MMap>
</React.Fragment>;

// ...
ReactDOM.render(<App />, document.getElementById("app"));
}

Detailed example.

Constructor

new MMapClusterer(props)

Constructor parameters

Parameter

Type

props

MMapClustererProps

Redefines

MMapComplexEntity.constructor

Props

MMapClustererProps: Object

Type declaration

Parameter

Type

Description

cluster

(coordinates: LngLat, features: Feature[]) => MMapEntity<unknown>

Function for creating a marker for a cluster.

features

Feature[]

Object for clusterization on the map.

marker

(feature: Feature) => MMapEntity<unknown>

Function for creating a marker for a point.

maxZoom?

number

Maximum zoom for clusterization. If you zoom out of the map, markers will be displayed as they are.

method

IClusterMethod

Clusterization method.

onRender?

(clusters: ClustererObject[]) => void | false

Returns false if rendering needs to be redefined.

tickTimeout?

number

Time that can elapse before the rendering method is called again.

Methods

update

update(changedProps): void

Parameters

Parameter

Type

Description

changedProps

Partial<MMapClustererProps>

New props values.

Returns

void

Inherited from

MMapComplexEntity.update