3D棱柱效果
上代码
var map = new BMapGL.Map("allmap");
var point = new BMapGL.Point(116.404, 39.925);
map.centerAndZoom(point, 10);
map.setTilt(50);
map.enableScrollWheelZoom();
var bd = new BMapGL.Boundary();
bd.get('北京市', function (rs) {
var count = rs.boundaries.length; //行政区域的点有多少个
var pointArray = [];
for (var i = 0; i < count; i++) {
var path = [];
str = rs.boundaries[i].replace(' ', '');
points = str.split(';');
for (var j = 0; j < points.length; j++) {
var lng = points[j].split(',')[0];
var lat = points[j].split(',')[1];
path.push(new BMapGL.Point(lng, lat));
}
var prism = new BMapGL.Prism(path, 5000, {
topFillColor: '#5679ea',
topFillOpacity: 0.5,
sideFillColor: '#5679ea',
sideFillOpacity: 0.9
});
map.addOverlay(prism);
}
});
这段代码是 百度地图文档-3D棱柱 的教程,好多人可能好奇,既然有教程,直接粘贴复制不就好了,为什么还要写这篇文章呢?
那是因为,上边的代码确实可以实现我们的想要的3D效果,但是如果你想让34个省级行政区域,都这样显示,那性能上就有点不友好了,要知道每个省的boundaries数据,可是非常非常多。所以这篇文章主要是为了解决边界数据进行抽取
中国34个省级行政区域
// 我国共有34个省级行政区域,包括23个省,5个自治区,4个直辖市,2个特别行政区
// 4个直辖市 北京市、重庆市、上海市、天津市
// 5个自治区:内蒙古自治区、广西壮族自治区、西藏自治区、新疆维吾尔自治区、宁夏回族自治区
// 2个特别行政区:澳门特别行政区、香港特别行政区
// 23个省 : 河北省(冀)、山东省(齐)、辽宁省(辽)、黑龙江省(黑)、甘肃省(陇)、吉林省(吉)、青海省(青)、河南省(豫)、江苏省(苏)、湖北省(鄂)、湖南省(湘)、浙江省(浙)、江西省(赣)、广东省(粤)、云南省(滇)、福建省(福)、台湾省(台)、海南省(琼)、山西省(晋)、四川省(川)、陕西省(陕)、贵州省(黔)、安徽省(皖)
创建过程
这里有个概念需要说一下,想实现3D效果主要需要以下3个点:
setTilt:地图倾斜角度(一般设置40-70,这样可以看到棱柱的侧边,出现3d效果)
Point:指定的经度和纬度创建一个地理点坐标
Prism:创建棱柱覆盖物
整体过程:
通过 省名称获取管辖下所有城市经纬度,然后遍历每个lng/lat,创建对应的Point,将所有的Point储存到数组内,当参数传入Prism,最后 addOverlay注入到地图上
优化思路
通过上边的描述,我们可以知道Point是点,Prism是覆盖物,setTilt是倾斜的角度。
那么是否可以通过既减少Point,又能实现3D效果呢?
// 百度地图API功能
var map = new BMapGL.Map("allmap");
var point = new BMapGL.Point(116.404, 39.925);
map.centerAndZoom(point, 10);
map.setTilt(50);
map.enableScrollWheelZoom();
var str='116.06028395672872,40.456532235828135;115.93135041154004,39.694265742564866;117.23750328236457,39.5034425351181;117.40567747174113,40.36225554457048';
var path=[];
var points = str.split(';');
for (var j = 0; j < points.length; j++) {
var lng = points[j].split(',')[0];
var lat = points[j].split(',')[1];
path.push(new BMapGL.Point(lng, lat));
}
var prism = new BMapGL.Prism(path, 5000, {
topFillColor: '#5679ea',
topFillOpacity: 0.5,
sideFillColor: '#5679ea',
sideFillOpacity: 0.9
});
map.addOverlay(prism);
效果
地图换算比例
说道这里,大家应该已经知道我的思路了,上边我说了所有城市经纬度boundaries数据,可是非常非常多,地图放大、缩小是有zoom级别的,我们肯定不需要在地图放大到最大状态下省边界数据,那么我能根据自己想放大的级别,做一下数据抽取就好了
'zoom6': 200000,
'zoom7': 100000,
'zoom8': 50000,
'zoom9': 25000,
'zoom10': 20000,
'zoom11': 10000,
'zoom12': 5000,
'zoom13': 2000,
'zoom14': 1000,
'zoom15': 500,
'zoom16': 200,
'zoom17': 100,
'zoom18': 50,
'zoom19': 20
动手优化
我们根据地图不同zoom级别下的换算比例,计算点与点的距离getDistance,如果小于xxx距离,我们就不在排除该经纬度,这样我们就可以抽取到缩减后的经纬度,效果是一样的!!!
export default {
data () {
return {
mapv_point:{},
zoomObj: {
'zoom6': 200000,
'zoom7': 100000,
'zoom8': 50000,
'zoom9': 25000,
'zoom10': 20000,
'zoom11': 10000,
'zoom12': 5000,
'zoom13': 2000,
'zoom14': 1000,
'zoom15': 500,
'zoom16': 200,
'zoom17': 100,
'zoom18': 50,
'zoom19': 20
},
zoom :6
}
},
mounted (){
this.map_boundary_fn('北京',this.zoom)
},
methods: {
map_boundary_fn (name,id) {
var bd= new BMapGL.Boundary()
var _this = this
bd.get(name, async function (rs) {
// 行政区域的点有多少个
var count = rs.boundaries.length
console.log(name, count, '-----------城市')
for (var i = 0; i < count; i++) {
var path = []
var str = rs.boundaries[i].replace(' ', '')
var points = str.split(';')
for (var j = 0; j < points.length; j++) {
var lng = points[j].split(',')[0]
var lat = points[j].split(',')[1]
const obj = await _this.mapv_point_fn({ lng, lat }, points, j)
j = obj.ind
path.push({ lng, lat })
}
_this.mapv_point['city' + id].arr.push(path)
}
})
},
mapv_point_fn (start, arr, ind) {
return new Promise((resolve, reject) => {
for (var i = ind; i < arr.length; i++) {
const obj = arr[i].split(',')
var pointA = new BMapGL.Point(start.lng, start.lat) // 创建点坐标A
var pointB = new BMapGL.Point(obj[0], obj[1]) // 创建点坐标B
var distance = this.map.getDistance(pointA, pointB).toFixed(1) * 1 // 获取两点距离,保留小数点后两位
if (distance > this.zoomObj['zoom' + this.zoom] / 100) {
resolve({
start,
end: { lng: obj[0], lat: obj[1] },
ind: i
})
i = arr.length + 1
} else if (i == arr.length - 1) {
console.log('-------结束了')
resolve({
start,
end: { lng: obj[0], lat: obj[1] },
ind: i
})
}
}
})
}
}
}
到这里就基本完成了,如果小伙伴们有不清楚、不同建议的地方,欢迎评论区留言~