高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

哈喽,各位高贵的倔友们你们好呀(✪ω✪),今天小编给各位分享一篇关于高德地图内容的文章,如果各位倔友觉得还不错,期望点个赞呗,那我们话不多说,直接进入正题。

写在开头

申请Web端开发者Key和安全密钥

要使用高德地图,我们必须先去高德地图官网注册成为开发者,并创建应用申请得到一个开发者 Key 与安全密钥。

注册/登录 -> 右上角头像 -> 应用管理 -> 点击”创建新应用”按钮 -> 添加 Key

上面我们简单给个过程路径就不再多说啦,很简单的,更加详细的过程可以看看这里。传送门

安装

然后我们需要安装高德地图的依赖包:

npm install @amap/amap-jsapi-loader --save

初始化地图

装好依赖后,就能初始化地图了。

新建 AreaMap.vue 文件:

<template>
  <div id="container" />
</template>

<script>
import AMapLoader from '@amap/amap-jsapi-loader';

export default {
  data() {
    return {
      // map:null, // 此处不声明 map 对象,可以直接使用 this.map 赋值或者采用非响应式的普通对象来存储。
    }
  },
  async mounted() {
    await this.initMap();
  },
  methods: {
    /** @name 初始化地图 **/
    initMap() {
      return new Promise(resolve => {
        window._AMapSecurityConfig = {
          securityJsCode: '你的安全密钥', // 自2021年12月02日升级后, key与安全密钥必须一起使用, 否则可能会出现一些API无法使用,如 DistrictSearch
        }
        AMapLoader.load({
          key: '你的Key', // 首次调用 load 时必填
          version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
          plugins: [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
        }).then((AMap)=>{
          this.map = new AMap.Map('container', {
            center: [110.17293, 35.20173],
            zoom: 4.8,
          });
          this.map.on('complete', () => {
            resolve();
          });
        }).catch(e=>{
          console.log(e);
        })
      })
    }
  }
}
</script>

<style scoped>
#container {
  width: 740px;
  height: 500px;
}
</style>

这里小编使用的是 Vue,对于其他技术栈初始化地图,可以看看这里传送门

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

数据准备

这里小编先准备了一些测试数据,下面会以这种数据结构来编写逻辑,如果你真实的数据结构与此不同,可以自行再转换一下或者适当调整一下代码逻辑。

创建 data.js 文件:

const data = [
  {
    "province": "北京市",
    "city": "北京城区",
    "area": "西城区",
    "append": "北京市北京城区西城区3",
    "lng": "116.365868",
    "lat": "39.912289",
  },
  {
    "province": "上海市",
    "city": "上海城区",
    "area": "静安区",
    "append": "上海市上海城区静安区5",
    "lng": "121.459384",
    "lat": "31.247105",
  },
  {
    "province": "广东省",
    "city": "广州市",
    "area": "黄埔区",
    "append": "广东省广州市黄埔区4",
    "lng": "113.459749",
    "lat": "23.106402",
  },
  {
    "province": "四川省",
    "city": "成都市",
    "area": "青羊区",
    "append": "四川省成都市青羊区6",
    "lng": "104.062499",
    "lat": "30.674406",
  },
  {
    "province": "河北省",
    "city": "石家庄市",
    "area": "桥西区",
    "append": "河北省石家庄市桥西区2",
    "lng": "114.461154",
    "lat": "38.004043",
  },
  {
    "province": "重庆市",
    "city": "重庆城区",
    "area": "涪陵区",
    "append": "重庆市重庆城区涪陵区1",
    "lng": "107.389298",
    "lat": "29.703113",
  },
];

export default data;

需要注意,上面小编虽然只列举了几条数据,但像这种以后可能会增大的数据量,一定不要直接挂载到 Vue 身上,要不消耗的依赖收集行为会特别影响性能!!!
不要问我为什么知道的(•́へ•́╬)。

地图板块颜色标注

完成准备工作后,我们就要进入本章的主题对“地图区域板块”进行自定义颜色标注,该功能主要使用到高德地图的 AMap.DistrictLayer
图层对象。

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

该对象使用方式很简单,我们主要关注它的 adcode 参数,它表示区域板块的行政编码,下面小编写了一个简单案例,请观看:

adcode 参数官方文档写得是 String 类型,但实际还支持 Array 类型。

<script>
export default {
  ...
  async mounted() {
    await this.initMap();
    // 初始完地图后,开始绘制
    this.drawAreaMap();
  },
  methods: {
    ...,
    /** @name 绘制区域地图 **/
    drawAreaMap() {
      const instance = new window.AMap.DistrictLayer.Province({
        adcode: ["310000", "110000", "510000", "440000", "130000", "500000", "500000"],
        depth: 0,
        styles: {
          'fill': 'red',
        },
      });
      instance.setMap(this.map);
    },
  }
}
</script>

具体效果:

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

是不是很简单(✪ω✪),然后你以为这就完了?当然还没,接下来我们需要解决两个问题。

  1. 开头我们提前准备的数据里面是没有行政编码的,这个行政编码只能从高德那边获取回来。
  2. 我们需要实现对不同区域板块标注不同的颜色。

获取行政编码

行政编码的获取,高德提供了一个 AMap.DistrictSearch 对象供我们查询,它属于额外的插件服务,需要在地图初始化的时候进行配置。

具体配置如下:

/** @name 初始化地图 **/
initMap() {
  return new Promise(resolve => {
    ...
    AMapLoader.load({
      key: '你的Key',
      version: '2.0',
      plugins: [ // 配置行政区查询服务
        'AMap.DistrictSearch'
      ],
    })
    ...
  })
}

后续如果使用到其他一些额外服务都是在 plugins 这里进行配置。

接下来我们就把数据的地址信息转换成具体的行政编码:

<script>
import AMapLoader from '@amap/amap-jsapi-loader';
import data from './data.js';

export default {
  ...
  async mounted() {
    await this.initMap();
    // 初始完地图后,开始绘制
    this.drawAreaMap();
  },
  methods: {
    ...,
    /** @name 绘制区域地图 **/
    drawAreaMap() {
      const allAdCode = await this.getAllAdCode();
      console.log('allAdCode', allAdCode);
      // 获取数据对应的"省级"行政编码
      const adcode = [];
      data.forEach(address => {
        allAdCode.districtList.forEach(province => {
          if(address.province === province.name) {
            adcode.push(province.adcode)
          }
        })
      })
    
      const instance = new window.AMap.DistrictLayer.Province({
        adcode,
        depth: 0,
        styles: {
          'fill': 'red',
        },
      });
      instance.setMap(this.map);
    },
    /** @name 获取所有区域板块的行政编码 **/
    getAllAdCode() {
      return new Promise(resolve => {
        const searchInstance = new window.AMap.DistrictSearch({
          subdistrict: 3, // 获取的下级行政区"级数"
          showbiz: false, // 是否显示商圈, 这里用不上直接false
        });
        searchInstance.search('中国', (status, result) => {
          if (status === 'complete') {
            resolve(result.districtList[0]);
          }
        });
      });
    }
  }
}
</script>

subdistrict 参数有四个值:0、1、2、3。默认值为 1, 其中 0 表示不返回下级行政区,1 表示返回下一级行政区,2 表示返回下两级行政区,3 表示返回下三级行政区。

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

getAllAdCode 方法中,小编直接把全国与省市区三级的行政编码一次性全部获取回来了,然后再通过循环去找到对应的数据,高德返回全国区域的行政编码其实是非常快的。

记得初次写得时候,小编是根据数据中需要哪个区域的数据就去查询那个区域,少量数据的话这样子是没有问题的,但是一旦数据量开始变多,并且查询的不是省级,是市级或者区级,那性能就嘎嘎往下掉。。。-.-

不同颜色标注

那么,现在地图中红色板块的标注就是根据”数据”来控制的了,但是全部都是红色的略显单调,小编这就来给它们分别上上色(✪ω✪)。

官方文档中对于板块的样式调整有六个参数可以使用,应该是足够满足我们实际中复杂的业务需求了。

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

具体过程如下:

<script>
export default {
  ...
  methods: {
    ...,
    /** @name 绘制区域地图 **/
    drawAreaMap() {
      ...
      const instance = new window.AMap.DistrictLayer.Province({
        adcode,
        depth: 0,
        styles: {
          // 填充色
          'fill': fillParams => {
             console.log(fillParams)
             const r = Math.floor(Math.random() * 255);
             const g = Math.floor(Math.random() * 255);
             const b = Math.floor(Math.random() * 255);
             const color = `rgba(${r}, ${g}, ${b}, 0.8)`;
             return adcode.includes(`${fillParams.adcode}`) ? color : undefined;
          },
        },
      });
      instance.setMap(this.map);
    },
  }
}
</script>

以上小编通过填充色 fill 支持的 Function 类型来实现不同颜色的标注,在回调函数中我们能获取到每个区域板块的行政编码。

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

省市区板块标注切换

上面我们标注的区域都是以省级为单位的,那么如何实现省级、市级、区级之间的标注切换呢?接下来请听小编细细道来(✪ω✪)。

前面我们知道了标注一块区域就需要知道这块区域的行政编码才行,那么问题转换成:

  • 省级:获取需要的省级行政编码
  • 市级:获取需要的市级行政编码
  • 区域:获取需要的区级行政编码

而且我们在上面的 allAdCode 变量中存储了全国所有区域板块的行政编码,它是一棵树形结构。

我们先看效果,再具体看编码过程:

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

<template>
<div class="map">
<div id="container" />
<select v-model="range" @change="rangeChange">
<option :value="'province'">省级</option>
<option :value="'city'">市级</option>
<option :value="'area'">区级</option>
</select>
</div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader';
import data from './data.js';
let instance = null;
export default {
data() {
return {
// map:null,
range: 'province'
}
},
...
methods: {
...,
/** @name 显示范围改变 **/
rangeChange() {
this.drawAreaMap();
},
/** @name 绘制区域地图 **/
drawAreaMap() {
const allAdCode = await this.getAllAdCode();
// 将树形转换成对象形式
const allAdCodeMap = this.transformTree(allAdCode);
// 获取行政编码
const adcode = [];
data.forEach(address => {
if (this.range === 'province') {
adcode.push(allAdCodeMap[address.province]?.adcode || '');
}
if (this.range === 'city') {
// 处理直辖市
const directCity = [
{ label: '北京市', value: '110000' },
{ label: '天津市', value: '120000' },
{ label: '重庆市', value: '500000' },
{ label: '上海市', value: '310000' },
{ label: '香港特别行政区', value: '810000' },
];
const target = directCity.find(item => item.label === address.province);
if (target) {
adcode.push(target.value);
} else {
adcode.push(allAdCodeMap[address.city]?.adcode || '');
}
}
if (this.range === 'area') {
adcode.push(allAdCodeMap[address.area]?.adcode || '');
}
});
// 重新绘制需要清空图层
instance && instance.setMap(null);
const depth = {
province: 0,
city: 1,
area: 2,
};
instance = new window.AMap.DistrictLayer.Province({
adcode,
depth: depth[this.range], // 设定数据的层级深度: https://lbs.amap.com/api/javascript-api-v2/documentation#districtlayer
styles: {
'fill': fillParams => {
const r = Math.floor(Math.random() * 255);
const g = Math.floor(Math.random() * 255);
const b = Math.floor(Math.random() * 255);
const color = `rgba(${r}, ${g}, ${b}, 0.8)`;
return adcode.includes(`${fillParams.adcode}`) ? color : undefined;
},
},
});
instance.setMap(this.map);
},
/** @name 将树形的行政编码转成对象形式 **/
transformTree(allAdCode) {
let allAdCodeMap = {};
if (this.range === 'province') {
allAdCodeMap = allAdCode.districtList.reduce((result, province) => {
result[province.name] = province;
return result;
}, {});
}
if (this.range === 'city') {
data.forEach(address => {
const province = allAdCode.districtList.find(
item => item.name === address.province,
);
if (province && province.districtList) { // 注意台湾省数据没有districtList
const cityMap = province.districtList.reduce((result, city) => {
result[city.name] = city;
return result;
}, {});
allAdCodeMap = {
...allAdCodeMap,
...cityMap,
}
}
})
}
if (this.range === 'area') {
data.forEach(address => {
const province = allAdCode.districtList.find(
item => item.name === address.province,
);
if (province && province.districtList) {
const city = province.districtList.find(
item => item.name === address.city,
);
if (city && city.districtList) {
const areaMap = city.districtList.reduce((result, area) => {
result[area.name] = area;
return result;
}, {});
allAdCodeMap = {
...allAdCodeMap,
...areaMap,
};
};
}
});
};
return allAdCodeMap;
},
}
}
</script>

编码过程不难,主要需要注意两点问题,其一是特殊省份像直辖市、台湾省、澳门等等,其二是性能问题。

主题风格切换

最后,我们再来完成一个地图主题风格切换的功能,高德地图官方给我们提供了十种标准的主题,可以直接免费使用,如果还不能满足你的需求,你也可以创建自定义的主题地图,当然,自定义功能强大只是需要花点 Money (✪ω✪)。传送门

因为比较简单,小编就直接来贴代码啦。

<template>
<div class="map">
...
<select v-model="style" @change="styleChange">
<option v-for="item in styleOptions" :key="item.value"  :value="item.value">
{{ item.label }}
</option>
</select>
</div>
</template>
<script>
...
export default {
data() {
return {
...,
style: 'normal',
styleOptions: [
{ label: '标准', value: 'normal' },
{ label: '幻影黑', value: 'dark' },
{ label: '月光银', value: 'light' },
{ label: '远山黛', value: 'whitesmoke' },
{ label: '草色青', value: 'fresh' },
{ label: '雅士灰', value: 'grey' },
{ label: '涂鸦', value: 'graffiti' },
{ label: '马卡龙', value: 'macaron' },
{ label: '靛青蓝', value: 'blue' },
{ label: '极夜蓝', value: 'darkblue' },
{ label: '酱籽', value: 'wine' },
]
}
},
...
methods: {
...,
/** @name 初始化地图 **/
initMap() {
return new Promise(resolve => {
window._AMapSecurityConfig = {
securityJsCode: '你的安全密钥',
}
AMapLoader.load({
key: '你的Key',
version: '2.0',
plugins: [
'AMap.DistrictSearch'
],
}).then((AMap)=>{
this.map = new AMap.Map('container', {
center: [110.17293, 35.20173],
zoom: 4.8,
mapStyle: 'amap://styles/' + this.style, // 加载主题
});
this.map.on('complete', () => {
resolve();
});
}).catch(e=>{
console.log(e);
})
})
},
/** @name 主题风格切换 **/
async styleChange() {
await this.initMap();
this.drawAreaMap();
},
}
}
</script>

具体实现效果:

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换


高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

哎,写到这里突然发现文章好像又贼拉长了,还有两个功能没写呢(“工具栏操作”、“地图板块交互事件”),呃……后面再写续集吧,溜了溜了。

完整源码

点我点我


至此,本篇文章就写完啦,撒花撒花。

高德地图-区域地图-实现对地图区域板块进行颜色标注与地图主题风格切换

希望本文对你有所帮助,如有任何疑问,期待你的留言哦。
老样子,点赞+评论=你会了,收藏=你精通了。

原文链接:https://juejin.cn/post/7266721485811712041 作者:橙某人

(0)
上一篇 2023年8月14日 上午10:41
下一篇 2023年8月14日 上午10:52

相关推荐

发表回复

登录后才能评论