Vue3项目里给高德地图加个‘省市区’三级联动高亮,我是这么做的

张开发
2026/4/8 18:05:38 15 分钟阅读

分享文章

Vue3项目里给高德地图加个‘省市区’三级联动高亮,我是这么做的
Vue3与高德地图实现省市区三级联动高亮的实战指南最近在开发一个物流配送系统时遇到了一个颇具挑战性的需求需要在地图上实现省-市-区三级行政区域的高亮联动展示。当用户选择某个省份时自动高亮该省下辖的所有市级区域选择某个市级区域时则高亮其下属的区县级区域。这种交互方式不仅能清晰展示行政层级关系还能为业务决策提供直观的地理信息支持。1. 环境准备与基础配置在开始编码前我们需要确保开发环境准备就绪。首先创建一个Vue3项目这里推荐使用Vite作为构建工具它能提供更快的开发体验。npm create vitelatest vue3-amap-demo --template vue cd vue3-amap-demo npm install amap/amap-jsapi-loader --save接下来我们需要申请高德地图的开发者密钥和安全密钥。这两个密钥是使用高德地图API的必要条件。申请完成后在项目根目录下创建.env文件存储这些敏感信息VITE_AMAP_KEY你的高德地图Key VITE_AMAP_SECURITY_CODE你的安全密钥在Vue组件中我们首先需要初始化地图实例。这里有几个关键点需要注意地图容器必须设置明确的宽高否则无法正常显示安全密钥配置必须在加载地图API前完成推荐使用异步加载方式引入高德地图API// MapContainer.vue script setup import { ref, onMounted } from vue import AMapLoader from amap/amap-jsapi-loader const map ref(null) const polygons ref([]) window._AMapSecurityConfig { securityJsCode: import.meta.env.VITE_AMAP_SECURITY_CODE } onMounted(async () { try { const AMap await AMapLoader.load({ key: import.meta.env.VITE_AMAP_KEY, version: 2.0, plugins: [AMap.DistrictSearch] }) map.value new AMap.Map(container, { viewMode: 2D, zoom: 4, center: [108.93984, 34.34127] }) } catch (error) { console.error(地图加载失败:, error) } }) /script2. 行政区划数据获取与处理实现三级联动的核心在于正确处理行政区划数据的层级关系。高德地图提供了DistrictSearch服务来获取这些数据我们需要根据不同的level参数获取不同层级的行政区域信息。2.1 行政区划级别参数说明高德地图DistrictSearch支持以下几种level参数参数值说明适用场景country国家级别显示全国地图province省级别省级区域展示city城市级别市级区域展示district区县级别区县级展示street街道级别详细街道展示对于我们的三级联动需求主要使用province、city和district这三个级别。2.2 获取下级行政区划数据当用户选择一个上级区域时我们需要获取其下辖的所有子区域信息。这里封装了一个通用的行政区查询函数const searchDistrict async (keyword, level) { if (!map.value) return // 清除现有多边形 clearPolygons() const districtSearch new AMap.DistrictSearch({ subdistrict: 1, // 获取下级行政区 extensions: all, level: level }) return new Promise((resolve) { districtSearch.search(keyword, (status, result) { if (status complete) { const districts result.districtList[0].districtList || [] resolve(districts.map(d ({ name: d.name, center: d.center, boundaries: d.boundaries }))) } }) }) }这个函数接收两个关键参数keyword: 要查询的行政区名称level: 查询的行政级别函数返回一个Promise解析后得到包含子区域名称、中心点和边界数据的数组。3. 实现三级联动交互有了基础的数据获取能力后我们可以着手实现三级联动的交互逻辑。这里采用Vue3的响应式特性来管理各级行政区划数据。3.1 组件状态设计首先定义组件的响应式状态const state reactive({ provinces: [], cities: [], districts: [], selectedProvince: null, selectedCity: null, selectedDistrict: null })3.2 联动逻辑实现三级联动的核心是当上级选择发生变化时自动加载并显示下级区域。我们为每个选择器绑定相应的事件处理函数template div classcontrols select v-modelstate.selectedProvince changeonProvinceChange option value选择省份/option option v-forprovince in state.provinces :valueprovince {{ province.name }} /option /select select v-modelstate.selectedCity changeonCityChange :disabled!state.selectedProvince option value选择城市/option option v-forcity in state.cities :valuecity {{ city.name }} /option /select select v-modelstate.selectedDistrict :disabled!state.selectedCity option value选择区县/option option v-fordistrict in state.districts :valuedistrict {{ district.name }} /option /select /div /template对应的处理函数实现const onProvinceChange async () { if (!state.selectedProvince) return state.cities await searchDistrict(state.selectedProvince.name, city) state.selectedCity null state.districts [] // 高亮显示选中的省份 highlightArea(state.selectedProvince.boundaries) } const onCityChange async () { if (!state.selectedCity) return state.districts await searchDistrict(state.selectedCity.name, district) state.selectedDistrict null // 高亮显示选中的城市 highlightArea(state.selectedCity.boundaries) }4. 地图高亮与性能优化当用户选择某个行政区域时我们需要在地图上高亮显示该区域。这看似简单但在处理大量多边形渲染时可能会遇到性能问题。4.1 基础高亮实现基本的区域高亮可以通过AMap.Polygon实现const highlightArea (boundaries) { clearPolygons() if (!boundaries) return const newPolygons boundaries.map(boundary { return new AMap.Polygon({ path: boundary, strokeColor: #1890ff, strokeWeight: 2, fillColor: #1890ff, fillOpacity: 0.4 }) }) polygons.value newPolygons map.value.add(newPolygons) map.value.setFitView(newPolygons) } const clearPolygons () { if (polygons.value.length) { map.value.remove(polygons.value) polygons.value [] } }4.2 性能优化策略在处理省级区域时边界数据可能非常复杂导致渲染性能下降。以下是几种有效的优化方法简化多边形路径使用简化算法减少多边形点数分级显示根据缩放级别显示不同精度的边界防抖处理对频繁的区域切换操作进行防抖Web Worker将繁重的计算任务放到Worker线程这里重点介绍路径简化策略。我们可以使用Douglas-Peucker算法来简化多边形const simplifyPath (path, tolerance 0.01) { if (path.length 2) return path // 实现Douglas-Peucker算法 // 这里省略具体实现代码 return simplifiedPath } const highlightArea (boundaries) { clearPolygons() if (!boundaries) return const newPolygons boundaries.map(boundary { const simplified simplifyPath(boundary) return new AMap.Polygon({ path: simplified, // 其他样式配置... }) }) // 剩余逻辑... }4.3 内存管理长时间运行的地图应用可能会因为不断创建新的多边形对象而导致内存增长。我们需要确保在不需要时及时清理onBeforeUnmount(() { clearPolygons() if (map.value) { map.value.destroy() map.value null } })5. 高级功能扩展基础的三级联动实现后我们可以考虑添加一些增强功能来提升用户体验。5.1 区域搜索功能为用户提供按名称搜索区域的能力const searchText ref() const searchResults ref([]) const handleSearch async () { if (!searchText.value.trim()) return const districtSearch new AMap.DistrictSearch({ subdistrict: 0, extensions: all, level: district }) districtSearch.search(searchText.value, (status, result) { if (status complete) { searchResults.value result.districtList } }) }5.2 多级同时高亮有时我们需要同时显示多个级别的区域比如显示一个省及其下辖的所有市const highlightProvinceWithCities async (province) { // 高亮省份 highlightArea(province.boundaries) // 获取并高亮所有市级区域 const cities await searchDistrict(province.name, city) cities.forEach(city { if (city.boundaries) { const cityPolygons city.boundaries.map(boundary { return new AMap.Polygon({ path: boundary, strokeColor: #52c41a, fillColor: #52c41a, fillOpacity: 0.3 }) }) map.value.add(cityPolygons) polygons.value.push(...cityPolygons) } }) map.value.setFitView(polygons.value) }5.3 自定义样式与交互为不同级别的区域设置不同的样式并添加交互事件const createPolygon (boundary, level) { const styles { province: { strokeColor: #1890ff, fillColor: #1890ff }, city: { strokeColor: #52c41a, fillColor: #52c41a }, district: { strokeColor: #fadb14, fillColor: #fadb14 } } const polygon new AMap.Polygon({ path: boundary, strokeWeight: 2, fillOpacity: 0.4, ...styles[level] }) // 添加鼠标交互 polygon.on(mouseover, () { polygon.setOptions({ fillOpacity: 0.6 }) }) polygon.on(mouseout, () { polygon.setOptions({ fillOpacity: 0.4 }) }) return polygon }6. 最佳实践与常见问题在实际项目中实现这类功能时有几个关键点需要特别注意密钥安全管理永远不要在前端代码中硬编码密钥使用环境变量存储敏感信息考虑通过后端代理请求高德API错误处理try { const districts await searchDistrict(name, level) // 处理数据... } catch (error) { console.error(获取行政区划数据失败:, error) // 显示友好的错误提示 }加载状态管理在获取数据时显示加载指示器处理网络不稳定的情况提供重试机制移动端适配确保地图容器响应式缩放优化触摸交互体验考虑移动端的性能限制浏览器兼容性测试不同浏览器下的表现必要时添加polyfill考虑使用WebGL渲染模式提升性能在最近的一个电商配送区域规划项目中这种三级联动高亮实现帮助业务团队直观地了解各层级配送范围大幅提高了区域划分的效率。特别是在处理像广东省这样下辖21个地级市的省份时优化后的渲染性能确保了流畅的交互体验。

更多文章