百度地图中自定义Marker、Label、InfoBox、Polyline、DrivingRoute

前言

一个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
})

自定义画线

  1. 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说明文档,其实很多可能我们看懂了这个文档,需求实现起来也变得很简单了。

相关推荐
m0_748255267 分钟前
前端安全——敏感信息泄露
前端·安全
鑫~阳2 小时前
html + css 淘宝网实战
前端·css·html
Catherinemin2 小时前
CSS|14 z-index
前端·css
漫天转悠2 小时前
Vue3项目中引入TailwindCSS(图文详情)
vue.js
qq_589568103 小时前
Echarts+vue电商平台数据可视化——后台实现笔记
vue.js·信息可视化·echarts
2401_882727573 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder3 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂3 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand4 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL4 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js