为了丰富地图的展示形式,研究了地图下钻功能,类似于DataV.GeoAtlas实现的效果,下面将实现的过程进行说明。
数据的准备
要实现地图下钻功能,首先按要求准备需要的数据,使字段对应。此处仍然已DataV.GeoAtlas上的数据为例进行说明,下面是在此网站上下载的吉林省各个市与各个市对应区县的geojson数据,然后按照一定的规则进行字段的设置,下图为最终设置好的字段名称与数据。
初始化地图
初始化地图,加载底图服务,然后加载事先准备好的吉林省各个市的数据,代码如下:
mapBoxMap.on("load", () => {
axios({url: cityUrl})
.then(function (res) {
//获取所有的city数据
cityFeature = res.data.features
mapBoxMap.addSource('my首页边界_200', {
'type': 'geojson',
'data': cityUrl
})
mapBoxMap.addLayer({
'id': '首页边界',
'type': 'fill',
'source': 'my首页边界_200',
'layout': {},
'paint': {
'fill-color': 'rgba(0,168,227,0)',
'fill-outline-color':'#01B3E9',
}
});
})
axios({url: quUrl})
.then(function (res) {
//获取所有的区县数据
quFeature = res.data.features
})
});
此处说明:最开始获取所有市和区县feature的目的是为了减少滑动时请求过慢造成的卡顿情况发生。
鼠标的滑动
地图下钻功能,可以分为鼠标划入划出的高亮、鼠标点击时的下钻。
先介绍鼠标的滑动时触发的事件流程:
mapBoxMap.on("mousemove",function (e) {
e.preventDefault()
let xy = mapBoxMap.project([e.lngLat.lng, e.lngLat.lat])
const features = mapBoxMap.queryRenderedFeatures(
[xy.x,xy.y],
{layers:["首页边界"]}
)
if(features.length > 0){
//不存在区县 市级别
if(!features[0].properties.name){
//判断当前选中的城市是否为鼠标滑过的城市
//不相同则进行新的数据加载
if(!(nowCityMove == features[0].properties.city)){
if (mapBoxMap.getSource('highLayerMouse')) {
mapBoxMap.removeLayer('highLayerMouse')
mapBoxMap.removeSource('highLayerMouse')
}
setTimeout(() => {
if (!mapBoxMap.getSource('highLayerClick')) {
mapBoxMap.getCanvas().style.cursor = 'pointer'
nowCityMove = features[0].properties.city
let featureNew = features[0].geometry
for(let i=0;i<cityFeature.length;i++){
if(features[0].properties.city == cityFeature[i].properties.city){
featureNew = cityFeature[i].geometry
break
}
}
showHighLayerMouse(featureNew)
}
})
}
}
else{
if(!(nowQuMove == features[0].properties.name)){
if (mapBoxMap.getSource('highLayerMouse')) {
mapBoxMap.removeLayer('highLayerMouse')
mapBoxMap.removeSource('highLayerMouse')
}
setTimeout(() => {
if (!mapBoxMap.getSource('highLayerClick')) {
mapBoxMap.getCanvas().style.cursor = 'pointer'
nowCityMove = features[0].properties.city
nowQuMove = features[0].properties.name
let featureNew = features[0].geometry
for(let i=0;i<quFeature.length;i++){
if((nowQuMove == quFeature[i].properties.name) && (nowCityMove == quFeature[i].properties.city)){
featureNew = quFeature[i].geometry
break
}
}
showHighLayerMouse(featureNew)
}
})
}
}
}
else{
nowCityMove =''
nowQuMove=''
//地图上的指针变成自动的
mapBoxMap.getCanvas().style.cursor = 'auto';
if (mapBoxMap.getSource('highLayerMouse')) {
mapBoxMap.removeLayer('highLayerMouse')
mapBoxMap.removeSource('highLayerMouse')
}
}
})
此处说明:首先判断划入时是否存在feature,不存在就都清空;如果存在,再判断划入时处于市级别还是区县级别,同时要判断划入处的城市名称是否为当前显示高亮的名称,避免抖动的情况;滑动最终效果如下:
鼠标的点击
接下来介绍鼠标点击时触发的事件流程:
mapBoxMap.on("click",function (e) {
let xy = mapBoxMap.project([e.lngLat.lng, e.lngLat.lat])
const features = mapBoxMap.queryRenderedFeatures(
[xy.x,xy.y],
{layers:["首页边界"]}
)
if(features.length > 0){
//不存在区县 市级别
if(!features[0].properties.name){
nowCityClick = features[0].properties.city
let allSources = mapBoxMap.getStyle().sources;
for (const key in allSources) {
if (allSources.hasOwnProperty(key) && /首页边界/.test(key)) {
if (mapBoxMap.getSource('my首页边界_200')) {
mapBoxMap.removeLayer('首页边界')
mapBoxMap.removeSource('my首页边界_200')
}
setTimeout(()=>{
mapBoxMap.addSource('my首页边界_200', {
'type': 'geojson',
'data': quUrl
});
mapBoxMap.addLayer({
'id': '首页边界',
'type': 'fill',
'source': 'my首页边界_200',
'layout': {},
'filter':['==', 'city', features[0].properties.city],
'paint': {
'fill-color': 'rgba(0,168,227,0)',
'fill-outline-color':'#01B3E9',
'fill-antialias':true
}
});
})
}
}
}
else{
if (mapBoxMap.getSource('highLayerPoint')) {
return
}else{
nowQuClick = features[0].properties.name
mapBoxMap.setFilter('首页边界',['all',['==','city',features[0].properties.city],['==','name',features[0].properties.name]]);
let featureNew = features[0].geometry
let bbox = turf.bbox(featureNew);
mapBoxMap.fitBounds([[bbox[0]-0.01, bbox[1]-0.01], [bbox[2]+0.01, bbox[3]+0.01]],{
linear: false,
animate: true,
})
showHighLayer(featureNew)
}
}
}
else{
if (mapBoxMap.getSource('highLayerClick')) {
mapBoxMap.removeLayer('highLayerClick')
mapBoxMap.removeSource('highLayerClick')
}
//地图上的指针变成自动的
mapBoxMap.getCanvas().style.cursor = 'auto';
if(nowQuClick == ''){
let allSources = mapBoxMap.getStyle().sources;
if(!(allSources['my首页边界_200'].data == cityUrl)){
if (mapBoxMap.getSource('my首页边界_200')) {
mapBoxMap.removeLayer('首页边界')
mapBoxMap.removeSource('my首页边界_200')
}
setTimeout(()=>{
mapBoxMap.addSource('my首页边界_200', {
'type': 'geojson',
'data': cityUrl
});
mapBoxMap.addLayer({
'id': '首页边界',
'type': 'fill',
'source': 'my首页边界_200',
'layout': {},
'paint': {
'fill-color': 'rgba(0,168,227,0)',
'fill-outline-color':'#01B3E9',
'fill-antialias':true
}
});
})
}
}
else{
nowQuClick = ''
mapBoxMap.setFilter('首页边界',['==','city',nowCityClick]);
}
}
})
此处说明:首先判断点击时是否存在feature,不存在判断处于哪一级别,进而来决定返回上一级别是什么;如果存在,再判断划入时处于市级别还是区县级别,同时要判断划入处的城市名称是否为当前显示高亮的名称,避免抖动的情况;点击最终效果如下:
总结
本文针对地图下钻功能的实现进行了说明,以后如果遇到新的功能再进行补充,接下来的章节将继续探索Mapbox。
欢迎关注星林社区,文章将同步更新在星林社区中!