地图 - 实现有多条定位,显示多条定位,并且使用一个圆形遮罩层将多条定位进行覆盖

首先,需要在你的index.html模板页面头部加载百度地图JavaScript API代码,密钥可去百度地图开放平台官网申请

然后,使用npm方式安装react组件库,然后通过es模块加载

npm install react-bmapgl --save

在需要显示地图的页面中编写

import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { Map, Marker, Circle } from 'react-bmapgl';

export default function ShopMapPage() {
  const location = useLocation();
  const record = location.state || {};  // 接收上个页面传递过来的地区数据,以便定位的显示

  useEffect(() => {
    // 加载百度地图脚本
    const loadMapScript = () => {
      return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src =
          'http://api.map.baidu.com/api?v=1.0&type=webgl&ak=您的密钥';
        script.onload = resolve;
        script.onerror = reject;
        document.body.appendChild(script);
      });
    };

    const geocode = (address: string) => {
      return new Promise((resolve, reject) => {
        const geocoder = new BMapGL.Geocoder();
        // 将地区转换为经纬度
        geocoder.getPoint(address, function (point) {
          if (point) {
            resolve(point);
          } else {
            reject('无法获取该地区的坐标');
          }
        });
      });
    };

    // 计算当前两个标记点之间的距离
    const getDistance = (point1: BMapGL.Point, point2: BMapGL.Point) => {
      const { lng: lng1, lat: lat1 } = point1;
      const { lng: lng2, lat: lat2 } = point2;
      // 在经纬度坐标系统中,经度和纬度通常以度(°)为单位表示。但是在计算距离或执行其他数学计算时,可能需要将角度转换为弧度(radian)来进行更准确的计算
      const radLng1 = lng1 * (Math.PI / 180); // lng1 是经度的值,乘以 (Math.PI / 180) 可以将其从度转换为弧度
      const radLat1 = lat1 * (Math.PI / 180);
      const radLng2 = lng2 * (Math.PI / 180);
      const radLat2 = lat2 * (Math.PI / 180);
      const a = Math.sin(radLat1) * Math.sin(radLat2); //调用 Math.sin() 方法计算出它们的正弦值,然后将两个正弦值相乘,即可得到参数 a 的值
      const b =
        Math.cos(radLat1) * Math.cos(radLat2) * Math.cos(radLng2 - radLng1);
      const distance = 6378137 * Math.acos(a + b); //调用 Math.acos() 方法,可以计算出两个点之间的弧度差,并将其乘以地球半径,就可以得到两个点之间的球面距离。
      return distance;
    };

    loadMapScript().then(() => {
      const map = new BMapGL.Map('mapContainer');

      // 地图放大缩写实现
      map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
      const scaleCtrl = new BMapGL.ScaleControl(); // 添加比例尺控件
      map.addControl(scaleCtrl);
      const zoomCtrl = new BMapGL.ZoomControl(); // 添加缩放控件(按钮)
      map.addControl(zoomCtrl);

      // const addresses = ['北京市海淀区', '北京市丰台区', '广州市天河区']; // 待转换的地区名称列表
      const addresses = [];
      if (record.length) {
        record.map((item: { city: string }) => {
          const result = item.city.replace(/\s/g, ''); // 使用正则表达式替换空格
          addresses.push(result);
        });
      } else {
        const result = record.city.replace(/\s/g, ''); // 使用正则表达式替换空格
        addresses.push(result);
      }

      Promise.all(addresses.map((address) => geocode(address)))
        .then((points) => {
          points.forEach((point) => {
            const marker = new BMapGL.Marker(point);
            map.addOverlay(marker);
          });

          // 如果地区有多条时,就出现遮罩层并且会根据多条定位调整位置并且缩放
          if (addresses.length > 1) {
            // 创建圆形遮罩层
            // 1. 使用 reduce() 方法将所有地理坐标点的经度 (lng) 和纬度 (lat) 分别累加。最终得到的 center 对象包含了所有点的经度和纬度之和。
            const center = points.reduce(
              (acc, point) => {
                return {
                  lng: acc.lng + point.lng,
                  lat: acc.lat + point.lat
                };
              },
              { lng: 0, lat: 0 }
            );
            // 2. 通过将经度和纬度分别除以标记点的数量 points.length,可以得到平均值,即标记点的中心坐标。
            center.lng /= points.length;
            center.lat /= points.length;
            // 3. 通过比较距离大小,找到最大的距离,将其存储在 maxDistance 变量中
            let maxDistance = 0;
            for (let i = 0; i < points.length; i++) {
              for (let j = i + 1; j < points.length; j++) {
                const distance = getDistance(points[i], points[j]); // getDistance()方法计算当前两个标记点之间的距离
                // 如果这个距离比目前的最大距离 maxDistance 要大,就将它赋值给 maxDistance
                if (distance > maxDistance) {
                  maxDistance = distance; //在所有的标记点对中,最终得到的 maxDistance 就是所有标记点之间的最大距离。
                }
              }
            }
            // 创建 BMapGL.Circle 对象时,需要传入三个参数:圆心坐标、半径和样式选项
            const circle = new BMapGL.Circle(center, maxDistance, {
              fillColor: '#454399', // 填充颜色
              // strokeColor: '#000', // 边框颜色
              strokeWeight: 1, // 边框宽度
              strokeOpacity: 0.8, // 边框透明度
              fillOpacity: 0.3 // 填充透明度
            });
            map.addOverlay(circle);

            const viewport = map.getViewport(points); //将地图的视野调整为适合包含所有标记点的最佳范围
            map.setViewport(viewport);
          } else {
            // 如果地区只有一条的时候,就将此定位设为中心并且设置缩放大小
            map.centerAndZoom(points[0], 11); //centerAndZoom() 是百度地图 API 中的一个方法,用于将地图中心点设置为指定的坐标,并设置地图的缩放级别。
          }
        })
        .catch((error) => {
          console.error(error);
        });
    });
  }, []);

  return (
    
); }

根据搜索的地区显示相对应的地图展示

地图 - 实现有多条定位,显示多条定位,并且使用一个圆形遮罩层将多条定位进行覆盖_第1张图片

地图 - 实现有多条定位,显示多条定位,并且使用一个圆形遮罩层将多条定位进行覆盖_第2张图片

根据单条信息点击时对应显示

地图 - 实现有多条定位,显示多条定位,并且使用一个圆形遮罩层将多条定位进行覆盖_第3张图片

你可能感兴趣的:(百度地图api,react)