Socket
Socket
Sign inDemoInstall

@yandex/ymaps3-clusterer

Package Overview
Dependencies
0
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @yandex/ymaps3-clusterer

Yandex Maps JS API 3.0 @yandex/ymaps3-clusterer


Version published
Weekly downloads
353
increased by41.2%
Maintainers
1
Install size
66.2 kB
Created
Weekly downloads
 

Readme

Source

@yandex/ymaps3-clusterer package


Using the clusterer helps to display a large number of markers on the map. When the scale of the map is increased, individual markers are combined into a cluster; when the map is scaled down, the cluster breaks up into individual markers.

npm version npm

How use

The package is located in the dist folder:

  • dist/types TypeScript types
  • dist/esm es6 modules for direct connection in your project
  • dist/index.js Yandex JS Module

to use Yandex JS Module you need to add your module loading handler to JS API

ymaps3.import.loaders.unshift(async (pkg) => {
  if (!pkg.includes('@yandex/ymaps3-clusterer')) {
    return;
  }

  if (location.href.includes('localhost')) {
    await ymaps3.import.script(`/dist/index.js`);
  } else {
    // You can use another CDN
    await ymaps3.import.script(`https://unpkg.com/${pkg}/dist/index.js`);
  }

  Object.assign(ymaps3, window[`${pkg}`]);
  return window[`${pkg}`];
});

and in your final code just use ymaps3.import

We will use these functions and constants in example:

const LOCATION = {center: [55.205247, 25.077816], zoom: 10};

const BOUNDS = [
  [54.58311, 25.9985],
  [56.30248, 24.47889]
];

const rndPoint = (bounds) => [
  bounds[0][0] + (bounds[1][0] - bounds[0][0]) * Math.random(),
  bounds[1][1] + (bounds[0][1] - bounds[1][1]) * Math.random()
];

/**
 * Generates randomly count points inside the BOUNDS area
 *
 * @param count
 * @param bounds
 * @returns {{geometry: {coordinates: *}, id, type: string, properties: {name: string}}[]}
 */
const getRandomPoints = (count, bounds) =>
  Array.from({length: count}, () => ({
    type: 'Feature',
    id: i++,
    geometry: {coordinates: rndPoint(bounds)},
    properties: {name: 'beer shop'}
  }));
main();
async function main() {
  await ymaps3.ready;
  const {YMap, YMapDefaultSchemeLayer, YMapLayer, YMapFeatureDataSource} = ymaps3;

  const {YMapClusterer, clusterByGrid} = await ymaps3.import('@yandex/ymaps3-clusterer@0.0.1');

  map = new YMap(document.getElementById('app'), {location: LOCATION});
  map
    .addChild(new YMapDefaultSchemeLayer())
    .addChild(new YMapFeatureDataSource({id: 'clusterer-source'}))
    .addChild(new YMapLayer({source: 'clusterer-source', type: 'markers', zIndex: 1800}));

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

  // Makes usual point Marker
  const marker = (feature) =>
    new ymaps3.YMapMarker(
      {
        coordinates: feature.geometry.coordinates,
        source: 'clusterer-source'
      },
      contentPin.cloneNode(true)
    );

  // Makes Cluster Marker
  const cluster = (coordinates, features) =>
    new ymaps3.YMapMarker(
      {
        coordinates,
        source: 'clusterer-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;
  }

  const clusterer = new YMapClusterer({
    method: clusterByGrid({gridSize: 64}),
    features: getRandomPoints(100, BOUNDS),
    marker,
    cluster
  });

  map.addChild(clusterer);
}

Or React version

main();
async function main() {
  const [ymaps3React] = await Promise.all([ymaps3.import('@yandex/ymaps3-reactify'), ymaps3.ready]);
  const reactify = ymaps3React.reactify.bindTo(React, ReactDOM);
  const {YMap, YMapDefaultSchemeLayer, YMapLayer, YMapFeatureDataSource, YMapMarker} = reactify.module(ymaps3);

  const {YMapClusterer, clusterByGrid} = reactify.module(
    await ymaps3.import('@yandex/ymaps3-clusterer@0.0.1')
  );
  const {useState, useCallback, useMemo} = React;
  const points = getRandomPoints(100, BOUNDS);
  const gridSizedMethod = clusterByGrid({gridSize: 64});

  function App() {
    const marker = useCallback(
      (feature) => (
        <YMapMarker key={feature.id} coordinates={feature.geometry.coordinates} source="clusterer-source">
          <img src="./pin.svg" className="pin" />
        </YMapMarker>
      ),
      []
    );

    const cluster = useCallback(
      (coordinates, features) => (
        <YMapMarker key={`${features[0].id}-${features.length}`} coordinates={coordinates} source="clusterer-source">
          <div className="circle">
            <div className="circle-content">
              <span className="circle-text">{features.length}</span>
            </div>
          </div>
        </YMapMarker>
      ),
      []
    );

    return (
      <>
        <YMap location={LOCATION} ref={(x) => (map = x)}>
          <YMapDefaultSchemeLayer />
          <YMapFeatureDataSource id="clusterer-source" />
          <YMapLayer source="clusterer-source" type="markers" zIndex={1800} />
          <YMapClusterer marker={marker} cluster={cluster} method={gridSizedMethod} features={points} />
        </YMap>
      </>
    );
  }

  const reactRoot = ReactDOM.createRoot(document.getElementById('app'));
  reactRoot.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );
}

More about working with the package

Example 1: Creating a Map and adding a Clusterer to the Map

We declare a variable for the map, load the ymaps3 library, extract the necessary classes.

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

  const {YMap, YMapDefaultSchemeLayer, YMapMarker, YMapLayer, YMapFeatureDataSource} = ymaps3;
  //...
}

We load the package with the clusterer, extract the classes for creating clusterer objects and the clustering method.

const {YMapClusterer, clusterByGrid} = await ymaps3.import('@yandex/ymaps3-clusterer@0.0.1');

Create and add to the map a layer with a default schema, data sources, a layer of markers.

const map = new YMap(document.getElementById('app'), {location: LOCATION});
map
  .addChild(new YMapDefaultSchemeLayer())
  .addChild(new YMapFeatureDataSource({id: 'my-source'}))
  .addChild(new YMapLayer({source: 'my-source', type: 'markers', zIndex: 1800}));

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

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

We declare the function for rendering ordinary markers, we will submit it to the clusterer settings. Note that the function must return any Entity element. In the example, this is ymaps3.YMapMarker.

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

As for ordinary markers, we declare a cluster rendering function that also returns an Entity element.

const cluster = (coordinates, features) =>
  new ymaps3.YMapMarker(
    {
      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;
}

Let's declare an array with marker coordinates, then create an array of features with the appropriate interface. We will pass it to the clusterer settings.

const coordinates = [
  [54.64, 25.76],
  [54.63, 25.7],
  [54.43, 25.69],
  [54.42, 25.127],
  [54.12, 25.437]
];

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

We create a clusterer object and add it to the map object. As parameters, we pass the clustering method, an array of features, the functions for rendering markers and clusters. For the clustering method, we will pass the size of the grid division in pixels.

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

map.addChild(clusterer);

Example 2. Using a Clusterer with React JS

We declare a variable for the map, load the ymaps3 library, extract the necessary classes.

window.map = null;
main();
async function main() {
  await ymaps3.ready;
  const ymaps3React = await ymaps3.import('@yandex/ymaps3-reactify');
  const reactify = ymaps3React.reactify.bindTo(React, ReactDOM);
  const {
    YMap,
    YMapDefaultSchemeLayer,
    YMapLayer,
    YMapFeatureDataSource,
    YMapMarker
  } = reactify.module(ymaps3);
  // ...
}

We connect the package with the clusterer, extract the classes for creating clusterer objects and the clustering method.

const {YMapClusterer, clusterByGrid} = reactify.module(
  await ymaps3.import('@yandex/ymaps3-clusterer@0.0.1')
);

We extract the necessary hooks. Let's declare an array with marker coordinates, then create an array of features with the appropriate interface. We will pass it to the clusterer settings.

const {useCallback, useMemo} = React;

const coordinates = [
  [54.64, 25.76],
  [54.63, 25.7],
  [54.43, 25.69],
  [54.47, 25.68],
  [54.53, 25.6],
  [54.59, 25.71],
  [54.5, 25.63],
  [54.42, 25.57],
  [54.12, 25.57],
  [54.32, 25.57]
];

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

We declare a render function. For the clustering method, we pass and store the size of one grid division in pixels.

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

We declare a function for rendering ordinary markers. Note that the function must return any Entity element. In the example, this is ymaps3.YMapMarker.

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

We declare a cluster rendering function that also returns an Entity element. We will transfer the marker and cluster rendering functions to the clusterer settings.

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

We return JSX, in which we render the components of the map, the default layer, data sources, the layer for markers and the clusterer. In the clusterer props, we pass the previously declared functions for rendering markers and clusters, the clustering method, and an array of features.

function App() {
  // ...
  return <>
    <YMap location={LOCATION} ref={x => map = x}>
      <YMapDefaultSchemeLayer />
      <YMapFeatureDataSource id="my-source" />
      <YMapLayer source="my-source" type="markers" zIndex={1800} />
      <YMapClusterer
        marker={marker}
        cluster={cluster}
        method={gridSizedMethod}
        features={points}
      />
    </YMap>
  </>;
}
// ...
ReactDOM.render(<App />, document.getElementById("app"));

FAQs

Last updated on 25 Apr 2024

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc