从零开始学高德地图,踩了很多坑,这次来给大家从实际业务讲起怎么在高德地图上显示车辆和轨迹点
下图为实例
使用的mock数据,只关注左上角即可
首先我们先搭建页面框架
<div className={style.container}>
<SplitPane split="horizontal" minSize={350} maxSize={400} pane2Style={{ width: '100%', height: '100%' }} style={{ position: 'relative', width: '100%', height: '100%' }}>
<SplitPane split="vertical" minSize={350} maxSize={700} pane2Style={{ width: '100%', height: '100%' }} defaultSize={700} style={{ position: 'relative', width: '100%', height: '100%' }}>
<Map></Map>
<CarList></CarList>
</SplitPane>
<div className={style.ticketShow}>
<TicketList></TicketList>
</div>
</SplitPane>
</div>
这里使用了react-split-pane这个npm包,可以动态调整div和div之间的布局,详情可以查看react-split-pane - npm (当然也可以直接把布局给固定)大家只需要关注map组件即可
之后我们写目录结构
|—compoent 存放组件的文件夹
|——carList.tsx 车辆列表组件(业务相关)
|——map.tsx 地图组件
|——TicketList.tsx 小票列表组件(业务相关)
|—index.ts 入口文件
|—location.tsx 框架文件
|—style.less 样式文件
如果要实时获取车辆定位,我们需要写一个全局websocket服务
const socket = require('socket.io-client')('---websocket服务地址---');
//socket连接服务
socket.on('connect', () => {
console.log('socket已连接');
});
//socket发送消息
export function socketEmit(params: any) {
console.log("发送的信息<---", params);
socket.emit('push_event', params);
}
//socket初始化并接收消息
//需要页面传递一个useModal的setState函数
export function socketInit(setState: (arg0: any) => void) {
socket.on('receive_event', (data: string) => {
console.log("接受的信息--->", data);
if (!data || data?.length == 0) {
//当data为空时,开始报错
return
}
//通过useModal实现全局广播
setState(data)
});
}
1.这是一个基于java的websocket服务,首先在工程启动的时候,就创建一个socket实例,之后用socket.on监听方法
2.发送socket和接受socket需要抛出为方法可以被其他组件使用
3.接受socket服务需要接收一个函数来将接受的信息持久化,这里是接受某个setState函数,当我们接受到socket信息之后,就会调用这个setState函数
需要注意的是,在开发过程中,一般map组件会接受多个和它同级的组件的数据,为了避免子传父再传子这一大坑,统一用了useModal进行全局状态管理
首先在map中写容器(需要定义高宽)
<div className={style.map}>
<div id='container' className={style.containerMap} />
</div>
之后创建一个地图实例
const [mapState, setMapState] = useState(null)
useEffect(() => {
initAMap()
}, [])
const initAMap = () => {
const geolocation = new AMap.Geolocation();
const toolbar = new AMap.ToolBar();
const map = new AMap.Map('container', { resizeEnable: true, center: [114.298572, 30.584355], zoom: 15 })
setMapState(map)
map.addControl(geolocation);
map.addControl(toolbar);
};
这里需要注意的是
1.使用useEffect在页面加载前执行高德地图的初始化函数,绑定在container这个dom下
2.将map实例使用useState保存在内存中,方便后期调用
之后,我们需要在接收到websocket服务后,在map上新增一个marker点标记
const [locationData, setLocationData] = useState([])
useEffect(() => {
socketInit(setLocationData)
})
其中,socketInit即全局socket服务的函数,接受了setLocationData这个函数,这样的话每次接受socket消息的时候都会触发该函数
最后,既然通过socket拿到了数据,我们可以直接处理数据,通过map.add即可
const [locationData, setLocationData] = useState([])
useEffect(() => {
socketInit(setLocationData)
})
useEffect(()=>{
const startContent = `<div class="section9 flex-col"><div class="box3 flex-row"><div class="box3 flex-row justify-between"><div class="arrows"></div><div class="wrap4 flex-col"></div><div class="TextGroup3 flex-col"><span class="txt13">${routerInfo?.stationName || '起点'}</span><span class="txt14">${deliverTime || ''}发车</span></div></div></div></div>`
const endContent = `<div class="section9 flex-col"><div class="wrap1 flex-row"><div class="wrap1 flex-row justify-between"><div class="arrows"></div><div class="main4 flex-col"></div><div class="TextGroup1 flex-col"><span class="word25">收货地址</span></div></div></div></div>`
const startMarker = new AMap.Marker({
content: startContent, // 自定义点标记覆盖物内容
// @ts-ignore
position: locationData[0], // 基点位置
extData: {
type: 'start',
},
});
map.add(startMarker);
//终点标记
const endMarker = new AMap.Marker({
content: endContent, // 自定义点标记覆盖物内容
// @ts-ignore
position: locationData[1], // 基点位置
extData: {
type: 'end',
},
});
map.add(endMarker);
map.setFitView()
},[locationData])