JavaScript实现百度地图建筑物边界(轮廓)高亮

1,400 阅读1分钟

前言

前段时间项目需要做一个联系页,需要在百度地图里将公司标注出来,效果类似这样:

image.png

开始

这需求不洒洒水。

image.png

直接翻看百度地图文档,但是找了半天没发现相关的API(找到的小伙伴告诉下我😭 ),怎么搞,又被产品坑了!!

image.png

秉着解决不了问题,就解决提出问题的人坚持不懈的精神,我打开了百度地图,并搜索了北京故宫博物院位置,发现百度地图做到了!

image.png

于是我打开了控制台,发现百度地图发起了一个请求,请求如下:

image.pngResponse中找到了对应的geo(墨卡托坐标,这里不做说明)

image.png

编码

app.js
import { parseGeo, coordinateToPoints } from 'utils'

const map = new BMap.Map('map');
map.centerAndZoom('北京故宫博物院', 14);
const geo = '...'; // 对应的geo
// 解析坐标
const geoObj = parseGeo(geo); 
// 转百度坐标
const boundaryPoints = coordinateToPoints(map, geoObj.points);
// 渲染高亮图层
drawPolygon(map, boundaryPoints);

function drawPolygon(map, points) {
    const polygon = new BMap.Polygon(points, {
        strokeWeight: 2,
        strokeColor: '#21B4C7',
        fillOpacity: 0.01, // 设置0无效
    });
    map.addOverlay(polygon);
    map.setViewport(polygon.getPath()); //调整视野
}
utils.js
/**
 * 墨卡托坐标解析
 * @param mocator
 * @return
 */
export function parseGeo(mocator) {
    if (typeof mocator != 'string') {
        return {};
    }
    var t = mocator.split("|");
    var n = parseInt(t[0]);
    var i = t[1];
    var r = t[2];
    var o = r.split(";");
    if (n === 4) {
        for (var a = [], s1 = 0; s1 < o.length - 1; s1++) {
            "1" === o[s1].split("-")[0] && a.push(o[s1].split("-")[1]);
        }
        o = a;
        o.push("");
    }
    var u = [];
    switch (n) {
        case 1:
            u.push(o[0]);
            break;
        case 2:
        case 3:
        case 4:
            for (var s = 0; s < o.length - 1; s++) {
                var l = o[s];
                if (l.length > 100) {
                    l = l.replace(/(-?[1-9]\d*\.\d*|-?0\.\d*[1-9]\d*|-?0?\.0+|0|-?[1-9]\d*),(-?[1-9]\d*\.\d*|-?0\.\d*[1-9]\d*|-?0?\.0+|0|-?[1-9]\d*)(,)/g,
                        "$1,$2;");
                    u.push(l);
                } else {
                    for (var c = [], d = l.split(","), f = 0; f < d.length; f += 2) {
                        var p = d[f];
                        var h = d[f + 1];
                        c.push(p + "," + h);
                    }
                    u.push(c.join(";"))
                }
            }
            break;
        default:
            break;
    }

    if (u.length <= 1) {
        u = u.toString();
    }

    var result = {
        type: n,
        bound: i,
        points: u
    };
    return result;
}

/**
 * 墨卡托坐标转百度坐标
 * @param map
 * @param coordinate
 * @return
 */
export function coordinateToPoints(map, coordinate) {
    var points = [];
    if (coordinate) {
        var arr = coordinate.split(";");
        if (arr) {
            for (var i = 0; i < arr.length; i++) {
                var coord = arr[i].split(",");
                if (coord && coord.length == 2) {
                    var mctXY = new BMap.Pixel(coord[0], coord[1]);
                    var project = map.getMapType().getProjection();
                    var point = project.pointToLngLat(mctXY);
                    points.push(new BMap.Point(point.lng, point.lat));
                }
            }
        }
    }
    return points;
}

效果

image.png

image.png

总结

由于需求只是高亮公司,所以我是使用静态渲染方式,需要动态获取geo的话,可以调用百度的接口。但是由于接口不在百度地图API规范里,可能导致某一天就无法调用了。

import qs from 'qs';

const params = {
  qt: 's',
  wd: '故宫博物院',
  wd2: '北京市东城区'
}
fetch(`https://map.baidu.com/?${qs.stringify(params)}`
).then(res => {

})