R1ZEN / react-yandex-maps

Yandex.Maps API bindings for React (fork https://github.com/gribnoysup/react-yandex-maps)
https://pbe-react-yandex-maps.vercel.app
MIT License
121 stars 20 forks source link

Невозможно получить список всех объектов в кластере #82

Open dapzer opened 6 months ago

dapzer commented 6 months ago

При вызове ymaps?.Clusterer.prototype.getGeoObjects() возваращаеться пустой массив, хотя на карте более 30 точек. Данные объекты нужны для того, что бы отобразить сразу все точки при помощи ymaps?.Map.prototype.setBounds

const DevicesMapContent = (props: DevicesMapProps) => {
  const { devices } = props;
  const intl = useIntl();
  const ymaps = useYMaps();

  useEffect(() => {
    if (ymaps && devices.length > 0) {
      console.log(ymaps?.Clusterer.prototype.getGeoObjects());

      ymaps?.Map.prototype.setBounds(ymaps?.Clusterer.prototype.getGeoObjects());
    }
  }, [ymaps, devices]);

  const getDeviceLabel = (device: RouterOnMap) => {
    const title = device.label || intl.formatMessage({ id: 'router.label.notSet' });
    const description = `(${device.clientLabel || intl.formatMessage({ id: 'router.label.notSet' })})`;
    const label = `${title} ${description}`;

    return !device.label && !device.clientLabel ? device.serial : label;
  };

  const customBalloonContentLayout = useMemo(() => {
    const item = `
      <div style="padding: 0; display: flex; flex-direction: column; gap: 10px;">
        {% for geoObject in properties.geoObjects %}
          {{ geoObject.properties.balloonContentBody|raw }}
        {% endfor %}
      </div>
    `;

    return ymaps?.templateLayoutFactory.createClass(item);
  }, [ymaps]);

  const getBaloonContent = (device: RouterOnMap) => {
    return `
      <div style="padding: 0;">
          <a target="_blank" href="/routers/${device.routerId}/status/interfaces" style="display: flex; align-items: center; gap: 4px">
            <img src="${router}" width="16" height="16">
            ${getDeviceLabel(device)}
          </a>
      </div>
    `;
  };

  return (
    <Map
      width={'100%'}
      height={'calc(100vh - 60px)'}
      options={{
        maxZoom: 20,
        minZoom: 3,
        autoFitToViewport: 'always',
        suppressMapOpenBlock: true,
        restrictMapArea: [
          [84.23618, -168.9],
          [-73.87011, 191],
        ],
      }}
      defaultState={{
        center: [55.751574, 37.573856],
        zoom: 9,
        behaviors: ['default', 'scrollZoom'],
      }}
    >
      <Clusterer
        options={{
          groupByCoordinates: false,
          clusterBalloonContentLayout: customBalloonContentLayout,
        }}
      >
        {devices.map(device => (
          <Placemark
            key={device.routerId}
            geometry={device.coordinates}
            properties={{
              balloonContentBody: getBaloonContent(device),
              hintContent: getDeviceLabel(device),
            }}
            onClick={() => {
              window.open(`/routers/${device.routerId}/status/interfaces`, '_blank');
            }}
            options={{
              hasBalloon: false,
              iconLayout: 'default#image',
              iconImageHref: routerWithShadow,
              iconImageSize: [54, 47],
              preset: 'islands#invertedVioletClusterIcons',
            }}
          />
        ))}
      </Clusterer>
    </Map>
  );
};

export const DevicesMap = (props: DevicesMapProps) => {
  return (
    <YMaps
      query={{
        apikey: yandexMapsApiKey,
        load: 'package.full',
      }}
    >
      <DevicesMapContent {...props} />
    </YMaps>
  );
};