vue中使用Echarts地理地图并结合高德地图实现一个国、省、市、区的地图下钻功能

编程入门 行业动态 更新时间:2024-10-13 12:20:42

vue中使用Echarts地理<a href=https://www.elefans.com/category/jswz/34/1770718.html style=地图并结合高德地图实现一个国、省、市、区的地图下钻功能"/>

vue中使用Echarts地理地图并结合高德地图实现一个国、省、市、区的地图下钻功能

vue中使用Echarts地理地图并结合高德地图实现一个国、省、市、区的地图下钻功能

  • 一、需求:按不同的层级展示不同的内容
    • 1.中国地图
    • 2.省级地图
    • 3.市级地图
    • 4.县和区以下的地图
  • 二、开发
    • 1. Echarts和地图容器的设置
      • 相关代码
    • 2. Echarts绘制
      • 相关代码
    • 2.Map绘制
      • 相关代码
  • 三、演示

一、需求:按不同的层级展示不同的内容

先放个UI图,这是要期望达到的效果

1.中国地图

点击带黄圈的深色区域可以进入对应的省份

2.省级地图

点击带黄圈的深色区域可以进入对应的地级市;点击返回上级可以回到中国地图

3.市级地图

点击带黄圈的深色区域可以进入对应的县区;点击返回上级可以回到市级
(注:右下角对应展示市级相关内容)

4.县和区以下的地图

高德地图展示对应设备具体位置及信息;点击返回上级可以回到县级
(注:此处高德地图点标记的添加可以看我之前我文章)

二、开发

重点来了!!!

1. Echarts和地图容器的设置

定义两个容器分别放置Echarts图表和高德地图
这里有个坑:我是通过控制display属性来控制这两个容器的显隐!!
那么为什么不用v-show和v-if呢?
1.v-show:Echarts图表在初始化过程中宽度会丢失,默认成为100px,这个我搜索过,碰到这问题的人很多
2.v-if:地图在加载以后无法隐藏,也就是实现不了返回上级的功能

相关代码

<template><div class="all-container">
<!--        背景地图--><div :style="`display: ${mapDisplay}`" class="map-container" id="Map"></div><div :style="`display: ${chartDisplay}`" class="equ-EchartContainer" ref="myEchart" id="myCharts"></div><div class="all-container">
<template>

2.script

data(){return {mapDisplay:'none',chartDisplay:'block',}
}

3.style

.all-container{position: relative;&::after { //伪元素添加背景图,可以控制背景图透明度content: "";display: inline-block;position: absolute;z-index: 0; //显示层级top: 0;left: 0;width: 100%;height: 100%;background: #f1f5fa url("../../../assets/img/equ/equ-map-bg.png") 63% 50% no-repeat;background-size: 720px;opacity: 0.5;}
}
.map-container{width: 100%;height: 825px;min-height: calc(100vh - 134px) !important;z-index: 1;/deep/.amap-info-content{ //修改高德地图组件默认样式padding: 0px;box-shadow: 0 0 6px 0 rgba(0,28,71,0.2);}/deep/.amap-info-close{display: none;}
}
.equ-EchartContainer {width: 100%;height: 825px;margin-left: 340px;min-height: calc(100vh - 134px) !important;z-index: 1;
}

2. Echarts绘制

相关代码

1.数据获取,以及相关数据格式定义

this.$axios.get('你自己获取数据的API').then(res => {if (res.code === 0 && res.data) {this.adCode = res.data.adCode //地图显示层级的行政区码,如当前为全国则传100000,浙江省传330000,杭州市...res.data.forEach((item) => {this.mapData.push({ //地图相关省、市、区数据'name': item.name, //城市名称'value':item.num, //相关设备数量(黄圈内的数字)'cityCode': item.adCode //行政区码})this.pointData.push({'name': item.name,'value':[item.lng,item.lat,item.num], //黄圈的经纬度及数字,这里也可以不传经纬度,在后续高德UI插件查询后可以加入'cityCode': item.adCode})})}
}).finally(()=>{if(!this.adCode){this.myEchart.showLoading(echartLoadingOptions); //E charts添加loading效果,可以去掉this.init(100000)}else {this.myEchart.showLoading(echartLoadingOptions);this.init(this.adCode)}
})

2.script相关代码

这里有个很大的坑,我找了好久也没找到一个合适的引入高德查询API的方法!!
此处引入方法load UI组件:

return new Promise((resolve, reject) => {AMapLoader.load({}}).then(() =>{new AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {var districtExplorer = new DistrictExplorer();districtExplorer.loadAreaNode(adcode, function (error, areaNode) {})})})
})

绘制:

import echarts from "echarts";export default {data() {return {option:null,myEchart:null,geoJson: {},}},mounted() {let myCharts = document.getElementById("myCharts");myCharts.style.width = window.innerWidth-480 + "px";  //初始化echarts图表宽度this.myEchart = echarts.init(this.$refs.myEchart);window.addEventListener("resize", this.handleResize);//根据窗口大小动态适配图表大小},beforeDestroy() {this.myEchart.clear(); //销毁window.removeEventListener("resize", this.handleResize);},methods:{//宽度适配handleResize() {let _this1 = this.myEchart;if (this.resizeTimer) {clearTimeout(this.resizeTimer);}this.resizeTimer = setTimeout(function () {let myCharts = document.getElementById("myCharts");myCharts.style.width = window.innerWidth-480 + "px";_this1.resize();}, 100);},//echarts图表绘制,传入显示层级的adcodeinit(adcode){this.getGeoJson(adcode).then(data => {this.geoJson = datathis.initEchartMap(this.mapData, this.pointData)})},//封装了高德地图AMapUI的行政区查询插件,传入显示层级的adcode,获取下属的行政区相关信息getGeoJson(adcode, childAdcode = '') {let _this = this;return new Promise((resolve, reject) => {AMapLoader.load({"key": "申请好的Web端开发者Key", // 必填"version": "1.4.15","AMapUI": {             // 是否加载 AMapUI,缺省不加载"version": '1.1',   // AMapUI 缺省 1.1"plugins":['geo/DistrictExplorer'],       // 需要加载的 AMapUI ui插件}}).then(() =>{new AMapUI.loadUI(['geo/DistrictExplorer'], DistrictExplorer => {var districtExplorer = new DistrictExplorer();districtExplorer.loadAreaNode(adcode, function (error, areaNode) {if (error) {console.error(error);reject(error);return;}let Json = areaNode.getSubFeatures();//console.log(_this.equRegisters)//此处判断是否到达区级以下if (Json.length === 0) {let parent = areaNode._data.geoData.parent.properties.acroutes;_this.myEchart.clear();_this.mapDisplay = 'block' //显示高德地图容器_this.chartDisplay = 'none' //隐藏图表_this.initMap() //绘制高德地图return;}if (childAdcode) {Json = Json.filter(item => {return item.properties.adcode == childAdcode;});}let mapJson = {features: Json};//返回查询到的相关的行政区信息resolve(mapJson);});});})})},//渲染echartsinitEchartMap(mapData, pointData) {//这里是绘制的重点,传入地图的格式以及行政区信息echarts.registerMap(this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国' ? 'china' : 'map', this.geoJson);//传入E charts图表相关数据,存入this.option中this.option = this.getOption(mapData,pointData);//loading加载用到,可以直接setOptio()if (this.isValidOption(this.option)) {this.myEchart.clear();this.myEchart.setOption(this.option, true)setTimeout(()=>{this.myEchart.hideLoading();},100)}//点击前解绑,防止点击事件触发多次this.myEchart.off('click');this.myEchart.on('click', this.echartsMapClick);},//loading加载用到,判断isValidOption(option) {return (this.isObject(option) &&!this.isEmptyObject(option) &&this.hasSeriesKey(option));},//loading加载用到,判断isObject(option) {return Object.prototype.isPrototypeOf(option);},//loading加载用到,判断isEmptyObject(option) {return Object.keys(option).length === 0;},//loading加载用到,判断hasSeriesKey(option) {return !!option["series"];},//echarts图表数据转换,传入地图省市数据和圆点数据getOption(mapData,pointData) {return {tooltip: {trigger: 'axis',axisPointer: {type: 'shadow'},},//地理地图绘制geo: {map: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国'? 'china' : 'map',zoom: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国'? 1.3 : 1,//aspectScale: 0.75, //长宽比roam: true,// 拖拽top: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国'? '17%' : '11%',left:'15%',scaleLimit:{ //缩放层级控制min: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国'? 1.3 : 1,max: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国'? 1.3 : 1,},label: {normal: {show: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国'? false : true,color: "rgb(249, 249, 249)", //省份标签字体颜色formatter: p => {switch (p.name) {case '内蒙古自治区':p.name = "内蒙古"break;case '西藏自治区':p.name = "西藏"break;case '新疆维吾尔自治区':p.name = "新疆"break;case '宁夏回族自治区':p.name = "宁夏"break;case '广西壮族自治区':p.name = "广西"break;case '香港特别行政区':p.name = "香港"break;case '澳门特别行政区':p.name = "澳门"break;}return p.name;}},emphasis: {show: true,color: '#8dd7fc',}},itemStyle: {normal: {areaColor: {type: 'linear',x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0, color: '#e9f5ff' // 0% 处的颜色}, {offset: 1, color: '#c2e5ff' // 100% 处的颜色}],global: false // 缺省为 false},borderColor: '#7abfff',borderWidth: 1,/*shadowBlur: 1,shadowColor: '#cbcaca',shadowOffsetX: 10,shadowOffsetY: 5,*/},emphasis: {areaColor: '#e9f5ff',borderWidth: 1.6,shadowBlur: 0,}},regions: [{name: "南海诸岛",itemStyle: {// 隐藏南海诸岛地图normal: {opacity: 0, // 为 0 时不绘制该图形}},label: {show: false // 隐藏文字}}],},//地图的渐变色层次区分visualMap: {min: 0,max: 100000,show: false,right: '3%',bottom: '5%',calculable: true,type: "piecewise",realtime: false,seriesIndex: [0],inRange: {color: ['#e9f5ff', '#c2e5ff', '#1E62AC','#467bc0']},pieces: [{min: 0,max: 0,label: '0',color: {type: 'linear',x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: '#e9f5ff'},{offset: 1,color: '#c2e5ff'}],globalCoord: false // 缺省为 false}}, {min: 1,max: 100,label: '<100',color: {type: 'linear',x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: '#83c4ff'},{offset: 1,color: '#2895ff'}],globalCoord: false // 缺省为 false}}, {min: 100,max: null,label: '>100',color: {type: 'linear',x: 0,y: 0,x2: 0,y2: 1,colorStops: [{offset: 0,color: '#89adff' // 0% 处的颜色},{offset: 1,color: '#2f65d5' // 100% 处的颜色}],globalCoord: false // 缺省为 false}}],textStyle: {color: '#24CFF4'}},series: [{type: 'map',geoIndex: 0,map: this.parentInfo.length === 1 && this.parentInfo[0].cityName === '全国' ? 'china' : 'map',roam: true,zoom: 1.3,showLegendSymbol: false, // 存在legend时显示label: {normal: {show: false,},emphasis: {show: false,}},data: mapData,}, {name: '散点',type: 'effectScatter',coordinateSystem: 'geo',rippleEffect: {brushType: 'fill'},hoverAnimation: true,itemStyle: {normal: {color: '#ff8400',shadowBlur: 0,shadowColor: '#333333'}},symbolSize: function (val) {let value = val[2];if (value > 100) {return 27}return 18},showEffectOn: 'render', //加载完毕显示特效normal: {show: true,color: '#fff',fontWeight: 'bold',position: 'inside',rich: {cnNum: {fontSize: 13,color: '#D4EEFF',}}},label: {normal: {show: true, //黄圈内添加数字color: '#ff8400',fontWeight: 'bold',position: 'inside',formatter: function (para) {return '{cnNum|' + para.data.value[2] + '}'},rich: {cnNum: {fontSize: 13,color: '#D4EEFF',}}},},data: pointData,},]}},//echarts点击有数据的省份或市,可以下钻echartsMapClick(params) {//console.log(params)if (!params.data) {return} else {//如果当前是最后一级,那就直接returnif (this.parentInfo[this.parentInfo.length - 1].code == params.data.cityCode) {return}let data = params.datathis.parentInfo.push({cityName: data.name,code: data.cityCode})this.getEquCount(data.cityCode) //这是我封装的获取数据的方法}},returnHome(){//因为最后一层肯定是高德地图,因此点击返回按钮,重新设置一下display属性,就能隐藏高德地图,显示E charts地图了,也不会影响echarts图表之间的层级切换this.mapDisplay = 'none' this.chartDisplay = 'block'if (this.parentInfo.length === 1) {return;}this.parentInfo.pop()if(this.parentInfo[this.parentInfo.length - 1].cityName === '全国'){this.getEquCount()}else {this.getEquCount(this.parentInfo[this.parentInfo.length - 1].code)}}},
}

2.Map绘制

定义

相关代码

1.获取数据

this.$axios.get('你自己获取数据的API').then(res => {if (res.code === 0 && res.data) {this.equRegisters = res.data.equRegisters}
})

2.绘制高德地图

import AMapLoader from '@amap/amap-jsapi-loader';
import { echartLoadingOptions } from "@/utils/constant";
export default {data() {return {option:null,equRegisters:[],}},methods:{//地图initMap() {//这里用了封装好的地图加载函数,不清楚的可以看我之前的文章this.$mapUtil.loadMap().then(AMap => {this.map = new AMap.Map('Map', {mapStyle: this.$mapUtil.mapStyle,zooms: [9, 18],zoom: 10,viewMode: "2D",resizeEnable: true,center: [104, 40],});//关联设备对应的图标this.addMarkerDetail()}).catch(() => {console.log('地图加载失败!')})},},//关联设备对应的图标addMarkerDetail() {let _this = this;//标记点的图标自定义var markers = [{icon: require('../../../assets/img/equ/map-pcw-4.png')},{icon: require('../../../assets/img/equ/map-pcw-5.png')}],],allMarkers=[];//这个是我相关的地图数据,也是后端返回的if (this.equRegisters && this.equRegisters.length > 0) {var infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(-19, -40),content: _this.$refs.equMarkerContent.$el});//地图加入对应关联设备类型的标记点for (let a = 0, y, x; a < this.equRegisters.length; a++) {x = this.getDetectorType(this.equRegisters[a].productName);y = this.changeStatus(this.equRegisters[a].status);if (this.equRegisters[a].longitude && this.equRegisters[a].latitude) {var markerType = new AMap.Marker({icon: new AMap.Icon({image: markers[x][y].icon,imageSize: new AMap.Size(34, 40),size: new AMap.Size(34, 40),}),position: [this.equRegisters[a].longitude, this.equRegisters[a].latitude],offset: new AMap.Pixel(-35, -35),//下面保存的是聚合点内想展示的数据,我没找到clusterData这个数据段的用法,暂时用这个我自定义的方法代替productName: this.equRegisters[a].productName,name: this.equRegisters[a].name,status: this.equRegisters[a].status,seqNo: this.equRegisters[a].seqNo,model: this.equRegisters[a].model,id: this.equRegisters[a].id,});//打开设备标记点窗体信息function onClearMarker(e) {infoWindow.open(_this.map, e.target.getPosition());_this.nowSelectedMarker = _this.equRegisters[a]}markerType.on('click', onClearMarker);/*markerType.on('mouseout', e => {_this.map.clearInfoWindow();});*/_this.map.add(markerType)//聚合点合集allMarkers.push(markerType);}}_this.map.setFitView(allMarkers)var _infoWindow = new AMap.InfoWindow({offset: new AMap.Pixel(0, -35),//挂载信息窗体的组件content: _this.$refs.equClusterContent.$el});//打开设备标记点窗体信息AMap.plugin(['AMap.MarkerClusterer'], () => {var cluster = new AMap.MarkerClusterer(_this.map, allMarkers, {gridSize: 80,//zoomOnClick:false, //聚合点点击控制,可以看官方开发文档});//信息窗体显隐控制cluster.on('click', clusterCallback);})function clusterCallback(e) {_this.nowClusterType = [];e.markers.forEach((item) => {_this.nowClusterType.push({'productName':item.w.productName,'name':item.w.name,'status':item.w.status,'seqNo':item.w.seqNo,'model':item.w.model,'id':item.w.id,})})var mapZoom = _this.map.getZoom(); //获取当前地图级别if(mapZoom === 18){_infoWindow.open(_this.map, [e.lnglat.lng,e.lnglat.lat]);}}//层级变换,清空窗体信息var logMapChange = function (){//var mapZoom = _this.map.getZoom(); //获取当前地图级别_this.map.clearInfoWindow();};_this.map.on('zoomchange', logMapChange);}},closeInfo(){let _this = this;_this.map.clearInfoWindow();},
}

3.信息窗体添加
(1)主文件内写入

<div style="display: none">//标记点信息窗体<markerContent @closeInfo="closeInfo" ref="equMarkerContent" :marker="nowSelectedMarker"></markerContent>//聚合点信息窗体<clusterContent @closeInfo="closeInfo" ref="equClusterContent" :cluster="nowClusterType"></clusterContent>
</div>
<script>
import markerContent from "./markerContent";
import clusterContent from "./clusterContent";
import equEchartMix from "@/components/device/equhome/equEchartMix";export default {name:'equMap',components:{markerContent,clusterContent},mixins: [equEchartMix],}
</script>

(2)标记点信息窗体(聚合点类似)
主要在于js代码里:

<template><div @click="closeInfo" class="close-icon"><svg-icon class="info-svg" icon-class="equ-close"/></div>
</template>
<script>
export default {name:'markerContent',props:{marker:{}},methods:{closeInfo() {//父子传递函数信息,关闭窗体this.$emit('closeInfo');},}
}
</script>

三、演示

链接: ==.html?pgcpgcid=UNjExNzkxMDQyNA%3D%3D&sharekey=d65f62f5b1297526bf7eb2e1e139bf024 .

更多推荐

vue中使用Echarts地理地图并结合高德地图实现一个国、省、市、区的地图下钻功能

本文发布于:2024-03-09 21:21:30,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1726134.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:地图   并结合   地理   功能   vue

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!