地图数据可视化-贝塞尔曲线
简介
本文将基于高德地图贝塞尔曲线相关api实现地址迁移可视化
效果预览

准备工作
本例主要使用React+React-Amap(基于React封装的高德地图组件)来实现,react-amap帮我们封装好了一些marker和覆盖物组件,使用起来相当方便,当然你也可以阅读学习后根据你当前的技术栈来进行改造
首先安装react-amap
yarn add react-amap
//or
npm install react-amap
1.绘制中心点
...
const centerMarkers = useMemo(() => {
return [
{
position: center,//center:[lng,lat] 地图中心点
offset: new AMap.current.Pixel(-9, -9), // 设置点标记偏移量
anchor: 'center',
},
];
}, [center]);
const centerMarkerRender = useCallback(() => {
return (
<div
className={style.center}
>
<div className={style.inner}></div>
</div>
);
}, []);
...
<Map
amapkey={amapkey}
events={mapEvents}
mapStyle="dark"
>
<Markers markers={centerMarkers} render={centerMarkerRender} />
</Map>
2.绘制迁移数据坐标点
const markers = useMemo(() => {
return list.map((item: any, index: number) => {
const { longitude, latitude, name, id, } = item;
return {
position: {
longitude,
latitude,
},
offset: new AMap.current.Pixel(-6, -10), // 设置点标记偏移量
anchor: 'center',
name,
id,
};
});
}, [list]);
const markerRender = useCallback(
(extData: any) => {
const {
name,
id,
} = extData as any;
return (
<div
className={style.markerItem}>
<div
className={style.title}
>
{name}
</div>
</div>
);
},
[markers],
);
...
<Map
amapkey={amapkey}
events={mapEvents}
mapStyle="dark"
>
...
<Markers markers={markers} render={markerRender} />
<Markers markers={centerMarkers} render={centerMarkerRender} />
</Map>
3.绘制贝塞尔曲线[参考]
//创建贝塞尔曲线对象
const createBezierCurve = useCallback(
(path: any[]) => {
return new AMap.current.BezierCurve({
path: path,
strokeColor:'#e5d035',
strokeOpacity: 1,
strokeWeight: 2,
isOutline:true,
outlineColor:'#fff',
borderWeight:1,
zIndex: 100,
});
},
[],
);
// 计算位置和曲率
const calcuLinePath = useCallback(
(list) => {
const { longitude: centerLng, latitude: centerLat } = center;
let newBezierCurveList = [];
list.forEach((item: any, index: number) => {
const { longitude, latitude } = item;
const radius = AMap.current.GeometryUtil.distance(
[centerLng, centerLat],
[longitude, latitude],
);
let lngFlag = longitude > centerLng ? 0.00001 : -0.00001;
let latFlag = latitude > centerLat ? 0.00001 : -0.00001;
if (longitude && latitude) {
var path = [
[centerLng, centerLat], //起点
//第一段弧线
[
centerLng + radius * Math.cos(25) * lngFlag,
centerLat + radius * Math.sin(25) * latFlag,
longitude,
latitude,
], //控制点,终点
];
const bezierCurve = createBezierCurve(path);
newBezierCurveList.push(bezierCurve);
bezierCurve.setMap(mapInst.current);
}
// 缩放地图到合适的视野级别
});
setBezierCurveList(newBezierCurveList);
mapInst.current.setFitView();
},
[
center,
],
);
首先要明确一个比例就是 经纬度/实际距离 约等于 100000/1
已知每条曲线的起点是地图中心点
那么利用简单的三角函数知识我们就可得知
曲线终点经度 = 地图中心点经度 + 迁移点与中心点距离 * Math.cos(25) * lngflag
lngflag是由迁移点经度和中心点经度比大小所得 表示在中心点的上方或下方
同理
曲线终点纬度 = 地图中心点纬度 + 迁移点与中心点距离 * Math.sin(25) * lngflag
注:这里三角函数的25度可以随意调整 也可以自己封装随机数函数来生成曲率角度
const getRandomIntInclusive = (min: number, max: number) => {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
};
最后按需添加css样式即可 略
4.总结
(1)由于我们是通过实例化对象来向地图中添加贝塞尔曲线的 所以当多次渲染时上次绘制的曲线需要手动清除
mapInst.current.remove(bezierCurveList);
mapInst是高德地图map event事件中created函数的回调参数 为当前地图实例[参考]
(2)通过设置每个迁移点marker的offset属性来解决曲线和坐标点位置偏移的问题
转载自:https://juejin.cn/post/7139810955126865951