首先,需要在你的index.html
模板页面头部加载百度地图JavaScript API代码,密钥可去百度地图开放平台官网申请
<script type="text/javascript" src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥"></script>
然后,使用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<void>((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<BMapGL.Point>((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 要大,就将它赋值给 maxDistanceif (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 (<div id="mapContainer" style={{ height: '45vw', width: '100%' }}></div>);
}
根据搜索的地区显示相对应的地图展示
根据单条信息点击时对应显示