uiwjs / react-amap

基于 React 封装的高德地图组件,帮助你轻松的接入地图到 React 项目中。
https://uiwjs.github.io/react-amap
MIT License
403 stars 64 forks source link

点击MarkerCluster聚合点获取的数组长度与实际不符 #340

Open AkimotoAkira77 opened 8 months ago

AkimotoAkira77 commented 8 months ago
// @ts-nocheck
import React, { useEffect, useState, useRef, useCallback } from "react";
import { getAllPoints } from "@/api";
import { Map, APILoader, Marker, Geolocation } from "@uiw/react-amap";
import myIcon from "@/assets/image/myIcon.png";

interface lnglat {
  longitude: number;
  latitude: number;
}

const MyPage: React.FC<any> = () => {
  const [point, setPoint] = useState<lnglat>({
    longitude: 121.49203,
    latitude: 31.24149,
  }); // 地图中心点
  const [points, setPoints] = useState<any[]>([]);

  const [map, setMap] = useState<any>(null);

  useEffect(() => {
    getPointsData();
  }, []);

  const getPointsData = async () => {
    try {
      const { code, msg, data } = await getAllPoints();
      if (code === 200) {
        setPoints(data);
      }
    } catch (e) {
      console.log("获取点位失败");
    }
  };

  const handleMarker = (markerData: any) => {};

  return (
    <div>
      <div>
        <APILoader
          akey="myKey"
          plugins={[
            "AMap.MarkerClusterer",
            "AMap.AutoComplete",
            "AMap.PlaceSearch",
          ]}
        >
          <Map
            zoom={19}
            zooms={[3, 19]}
            center={[point.longitude, point.latitude]}
            ref={(instance) => {
              if (instance && instance.map && !map) {
                setMap(instance.map);
              }
            }}
            onClick={(e) => {
              console.log(e);
            }}
          >
            <MarkerCluster points={points} handleMarker={handleMarker} />
          </Map>
        </APILoader>
      </div>
    </div>
  );
};

export default MyPage;

let cluster: any;

const MarkerCluster = (props: any) => {
  // eslint-disable-next-line react/prop-types
  const { AMap: AMap, map, container, points, handleMarker } = props;
  const gridSize = 60;

  useEffect(() => {
    if (!!points && points.length > 0) {
      addCluster();
    }
    return () => {
      if (cluster) {
        cluster.setMap(null);
      }
      cluster = null;
    };
  }, [points, cluster]);

  const _renderMarker = function (context: any) {
    // console.log("context", context?.data);
    // const content =
    //   '<div style="background-color: hsla(180, 100%, 50%, 0.3); height: 18px; width: 18px; border: 1px solid hsl(180, 100%, 40%); border-radius: 12px; box-shadow: hsl(180, 100%, 50%) 0px 0px 3px;"></div>';
    // context.marker.setContent(content);
    const offset = new AMap.Pixel(-11, -22);
    // const anchor = new AMap.Anchor(6,6)
    const icon = new AMap.Icon({
      imageSize: new AMap.Size(22, 22),
      image: myIcon,
    });
    context.marker.setIcon(icon);
    // context.marker.setAnchor([6,6])
    context.marker.setOffset(offset);
    // context.marker.on("click", e => {
    //   console.log("click", e, e.target.getExtData());
    // });
  };
  const sts = [
    {
      url: "https://webapi.amap.com/theme/v1.3/m1.png",
      size: new AMap.Size(53, 53),
      offset: new AMap.Pixel(-26, -26),
    },
    {
      url: "https://webapi.amap.com/theme/v1.3/m2.png",
      size: new AMap.Size(56, 56),
      offset: new AMap.Pixel(-28, -28),
    },
    {
      url: "https://webapi.amap.com/theme/v1.3/m3.png",
      size: new AMap.Size(66, 66),
      offset: new AMap.Pixel(-33, -33),
    },
    {
      url: "https://webapi.amap.com/theme/v1.3/m4.png",
      size: new AMap.Size(78, 78),
      offset: new AMap.Pixel(-39, -39),
    },
    {
      url: "https://webapi.amap.com/theme/v1.3/m5.png",
      size: new AMap.Size(90, 90),
      offset: new AMap.Pixel(-45, -45),
    },
  ];
  const addCluster = () => {
    if (!!cluster || points.length < 1) {
      cluster.setMap(null);
    } else if (points.length > 0) {
      cluster = new AMap.MarkerCluster(map, points, {
        styles: sts,
        gridSize: 60,
        minClusterSize: 10,
        // renderClusterMarker: _renderClusterMarker, // 自定义聚合点样式
        renderMarker: _renderMarker,
      });
      cluster.on("click", (e: any) => {
        console.log("聚合data", e?.clusterData);
        if (e?.clusterData?.length === 1) {
          // 处理单点业务逻辑
          const markerData = e?.clusterData[0];
          handleMarker(markerData);
        } else {
          // 两个点以上
        }
      });
    }
  };
  return <div></div>;
};

6a0ddf7f96e4b678a90b2e35d032468

我这边使用官方的MarkerCluster插件,可以显示聚合类,然后就是有个需求就是点2-10的聚合点时展示一个弹框列表,我这边打印e?.clusterData,发现数组长度有时会比显示的聚合数量少,甚至五千多的聚合点点出来length只有二十几个,请问可能是啥问题

jaywcjlove commented 8 months ago

@AkimotoAkira77 我看到你使用的是原生 api, 这极有可能是你的 key 限制,看一下官方文档,最快捷的方式是,提工单问客服

edk24 commented 3 months ago

更新一下解决办法,我问题和楼主一样。提工单问了

  1. AMap.MarkerCluster 别用 AMap.MarkerClusterer
  2. 应该取 clusterData[n]['_amapMarker'].originData

给出我的代码;

let ambulancePoints: AmbulancePoint[] = [];
clusterData.forEach((item) => {
  ambulancePoints = ambulancePoints.concat(item['_amapMarker'].originData[0])
})

originData 是原始数据,这东西在文档上也没有写 实属有点坑啊

不知道为什么 originData 也是个二维数组,我看了都只有一个成员, 就取了 0

来个大佬解释一下