前言
一个vue3项目有个大屏模块,需要使用地图。由于自己之前开发过地图相关功能,这次需求要的也急,所以地图就交由我负责开发。
因为是大屏,领导对UI的要求比较高,很多都需要自定义样式。需求也比较赶,有些地方没有思考清楚。刚好通过这篇文章好好总结一下。
初始化地图
<div class="map-box" ref="mapRef"></div>
js
const mapRef = ref()
const map = ref()
const initMap = () => {
map.value = new BMapGL.Map(mapRef.value)
onCenterAndZoom()
onScaleCtrl()
onZoomCtrl()
onSetMapStyleV2()
}
// 设置地图中心点
const onCenterAndZoom = (lng = 114.311754, lat = 30.598604, zoom = 15) => {
var point = new BMapGL.Point(lng, lat)
map.value.centerAndZoom(point, zoom)
}
// 添加比例尺控件
const onScaleCtrl = () => {
var scaleCtrl = new BMapGL.ScaleControl()
map.value.addControl(scaleCtrl)
}
// 添加缩放控件
const onZoomCtrl = () => {
var zoomCtrl = new BMapGL.ZoomControl({
anchor: BMAP_ANCHOR_TOP_RIGHT,
})
map.value.addControl(zoomCtrl)
map.value.enableScrollWheelZoom()
}
// 个性化地图设置
const onSetMapStyleV2 = () => {
map.value.setMapStyleV2({
styleId: '你在后台设置地图个性化的id',
})
}
自定义点、文本标注、信息窗口
js
const initMap = () => {
......
onSetMarkerLabelInfo()
}
const onSetMarkerLabelInfo = () => {
onCenterAndZoom(AREA_POINT.hanyang.lng, AREA_POINT.hanyang.lat, 14) // 根据自己情况设置
Object.keys(AREA_POINT).forEach(area => {
onSetMarker(AREA_POINT[area])
onSetLabel(AREA_POINT[area])
})
}
const onSetMarker = (item) => {
const myIcon = new BMapGL.Icon(areaImg, new BMapGL.Size(200, 150))
const ponit = new BMapGL.Point(item.lng, item.lat)
let marker = new BMapGL.Marker(ponit, {
icon: myIcon
})
const infoBox = onSetInfo(item)
marker.addEventListener('click', function () {
console.log('Marker:', '触发点击事件')
infoBox.open(marker)
})
map.value.addOverlay(marker)
}
const onSetLabel = (item) => {
const ponit = new BMapGL.Point(item.lng, item.lat)
var opts = {
position: ponit, // 指定文本标注所在的地理位置
offset: new BMapGL.Size(-32, -65), // 设置文本偏移量
}
var label = new BMapGL.Label('', opts)
label.setContent(`
<div class="label">${item.label}</div>
`)
label.setStyle({
border: 'none',
background: 'transparent',
})
map.value.addOverlay(label)
}
const roadDetailAction = (item) => {
// 注意这里的方法书写(单引号) 还是传参个方式
console.log(2222, item)
}
const onSetInfo = (item) => {
const html = `<div class="info-box">
<div class="title">${item.label || '-'}</div>
<div class="desc">描述信息</div>
<div onClick='roadDetailAction(${JSON.stringify(item)})' class="detail-row"><a>查看详情</a><img class="arrow-img" src="${arrowIcon}" alt="" /></div>
</div>`
const infoBox = new BMapGLLib.InfoBox(map.value, html, {
boxStyle: {
//设置样式
opacity: '1',
padding: '0px',
width: '300px',
height: '100px',
},
closeIconMargin: '6px 12px 0 0', //关闭图标举例右上角的间距
closeIconUrl: iconClose, //关闭图标的图片路径
// enableAutoPan: true,
align: INFOBOX_AT_TOP, // InfoBox显示位置,目前只有上和下
offset: new BMapGL.Size(20, 80), //InfoBox的偏移量
})
infoBox.enableAutoPan() // 是否启动自动平移功能
return infoBox
}
- 现在我们想在打开每个信息弹窗的时候关闭上一次打开的弹窗
js
const lastInfoBox = ref()
marker.addEventListener('click', function () {
console.log('Marker:', '触发点击事件')
// 判断上一个信息窗体是否存在,存在执行close
if (lastInfoBox.value) lastInfoBox.value?.close()
infoBox.open(marker)
lastInfoBox.value = infoBox
})
自定义画线
-
Polyline
Polyline 我们可以用来画线;我们可以根据后端返回的一系列坐标点集合自定义画路线。
js
const pointList = [[114.251609,30.558589],[114.249974,30.555152],[114.25116,30.553193],[114.252364,30.552354],[114.254879,30.551794],[114.257358,30.551358],[114.25986,30.551472]]
const onSetPolyline = () => {
const pointsList = pointList.map(i => new BMapGL.Point(i[0], i[1]))
let polyline = new BMapGL.Polyline(pointsList, {
strokeColor: 'red',
strokeWeight: 8,
})
map.value.addOverlay(polyline)
}
对于线路我们想点击弹出这条路线的信息弹窗。
js
const pointList = [[114.251609,30.558589],[114.249974,30.555152],[114.25116,30.553193],[114.252364,30.552354],[114.254879,30.551794],[114.257358,30.551358],[114.25986,30.551472]]
const onSetPolyline = () => {
const pointsList = pointList.map(i => new BMapGL.Point(i[0], i[1]))
let polyline = new BMapGL.Polyline(pointsList, {
strokeColor: 'red',
strokeWeight: 8,
})
map.value.addOverlay(polyline)
onSetPolylineInfo(polyline)
}
const onSetPolylineInfo = (polyline) => {
const html = `<div class="info-box">
<div class="title">解放大道</div>
<div class="desc">表述信息</div>
</div>`
const infoBox = new BMapGLLib.InfoBox(map.value, html, {
boxStyle: {
//设置样式
opacity: '1',
padding: '0px',
width: '300px',
height: '100px',
},
closeIconMargin: '6px 12px 0 0', //关闭图标举例右上角的间距
closeIconUrl: iconClose, //关闭图标的图片路径
// enableAutoPan: true,
align: INFOBOX_AT_TOP, // InfoBox显示位置,目前只有上和下
offset: new BMapGL.Size(20, 0), //InfoBox的偏移量
})
infoBox.enableAutoPan() // 是否启动自动平移功能
polyline.addEventListener('click', function (e) {
console.log('polyline点击')
// 判断上一个信息窗体是否存在,存在执行close
if (lastInfoBox.value) lastInfoBox.value?.close()
onOpenPolylineInfoBox(e, infoBox)
lastInfoBox.value = infoBox
})
}
const onOpenPolylineInfoBox = (e, infoBox) => {
var point = new BMapGL.Point(e.latLng.lng, e.latLng.lat)
var marker = new BMapGL.Marker(point)
infoBox.open(marker)
}
这里需要注意的是我们点击线条怎么处理点击的地方,弹出信息窗口。逻辑就是拿到点击位置的坐标创建Marker
以此来打开信息窗口。
- DrivingRoute
有时候可能只给到我们起始、终点坐标,让我们绘制线路图,这时我们就可以使用DrivingRoute
来实现。
js
const initMap = () => {
......
onSetDrivingRoute()
}
const onSetDrivingRoute = () => {
var driving = new BMapGL.DrivingRoute(map.value, {
renderOptions: {
map: map.value,
autoViewport: true,
},
})
driving.setPolylinesSetCallback(function(routes) {
// 用过方法找到Polyline 然后移除掉 再通过方法获取到所有路线上点 再绘制路线
const curLine = driving.getResults().getPlan(0).getRoute(0).getPolyline()
map.value.removeOverlay(curLine)
// 获取到途经点坐标
var pts = driving.getResults().getPlan(0).getRoute(0).getPath()
var polyline = new BMapGL.Polyline(pts, {
strokeColor: 'blue',
strokeWeight: 8,
})
map.value.addOverlay(polyline)
})
// //重新设置起始点,终点图标和偏移
var startIcon = new BMapGL.Icon(startImg, new BMapGL.Size(30, 50));
var endIcon = new BMapGL.Icon(endImg, new BMapGL.Size(30, 50));
var start = new BMapGL.Point(114.251609, 30.558589)
var end = new BMapGL.Point(114.25986,30.551472)
// 设置添加标注后的回调函数
driving.setMarkersSetCallback(function(result){
// 把自带的图标全部清空 再根据自己需要去添加自定义点图标 其实就是在坐标上添加覆盖物
map.value.clearOverlays()
var marker1 = new BMapGL.Marker(start, {icon: startIcon, offset: new BMapGL.Size(0, -20)})
var marker2 = new BMapGL.Marker(end, {icon: endIcon, offset: new BMapGL.Size(-15, -20)})
map.value.addOverlay(marker1)
map.value.addOverlay(marker2)
})
driving.search(start, end)
}
上面代码我们可以自定义修改驾车线路的样式。
总结
该文章总结了下这次项目用到的一些方法。主要就是当时没有时间去研究驾车方法自定义样式问题,后面一起研究了下进行了总结。
百度地图里面还有很多没有涉及,大家有兴趣可以自己研究。比如以前使用过的路书、地址解析等。
很多人可能不太愿意看它类的api说明文档,其实很多可能我们看懂了这个文档,需求实现起来也变得很简单了。