首先,需要在你的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 要大,就将它赋值给 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 (
<div id="mapContainer" style={{ height: '45vw', width: '100%' }}></div>
);
}
根据搜索的地区显示相对应的地图展示
根据单条信息点击时对应显示