效果如图所示
组件环境准备:
MapPage.vue
<!--针对于/mappage 这条路径显示 测试显示组件-->
<template>
<div class="comP1">
<Map></Map>
</div>
</template>
<script>
import Map from "@/components/Map";
export default {
name: "MapPage",
components:{Map}
}
</script>
<style scoped>
</style>
Map.vue
<!-- 显示商家地图分布的图表 -->
<template>
<div class="comP2" ref="map_1" @dblclick="revertMap"></div>
</template>
<script>
export default {
data () {
return {}
},
methods: {}
}
</script>
<style lang="less" scoped>
</style>
mounted挂载 执行内容 创建实例 请求数据 渲染图表 添加窗口尺寸变化的监听
mounted() {
// 渲染DOM元素之后 初始化图表实例 请求数据 监听页面尺寸变化
this.initChart()
this.getData()
window.addEventListener('resize',this.screenAdapter)
this.screenAdapter()
},
显示地图
- 获取中国地图矢量数据(这里的中国地图属性是直接从public/static静态文件拿到的)
- 注册地图数据到 全局echarts对象 中
- 配置 geo
- 在地图实例渲染出来之后 this.$nextTick 来添加 点击事件
import axios from 'axios' import {getProvinceMapInfo} from "@/utils/map_utils";引入 axios 因为初始的地图直接从本地静态资源获取 不用全局的 127.0.0.1
引入工具函数
async initChart(){
this.chartsInstance = this.$echarts.init(this.$refs.map_1, this.theme)
// 请求地图数据
const res = await axios.get('http://localhost:2904/static/map/china.json')
// 注册地图 registerMap('起名',数据源)
this.$echarts.registerMap('china',res.data)
const initOption ={
title:{
text:'▎ 战区据点分布',
left:20,
top:20
},
geo:{
type:'map',
map:'china',
top: '5%',
bottom:'5%',
itemStyle:{
areaColor:'#2e72bf',
borderColor:'#364466'
}
},
legend: {
left: '5%',
bottom: '5%',
orient:'vertical' // 可选提示竖向排列
}
}
this.chartsInstance.setOption(initOption)
// 在第一次设置图表完成之后 再去添加事件
this.$nextTick( function () {
// 得到的是点击省份中文 通过工具 转成拼音+路径 请求对应的省份数据
this.chartsInstance.on('click',this.dblData)
})
},
地图渲染出来后获取散点图数据 添加到新的系列当中 重新更新图表
请求过来散点图的数据:
[
{
"name": "中欣南部战区",
"children": [
{
"name": "武汉",
"value": [114.31, 30.52]
}, {
"name": "丹东",
"value": [124.37, 40.13]
}, {
"name": "张家口",
"value": [114.87, 40.82]
}, {
"name": "深圳",
"value": [114.07, 22.62]
}
]
},
{
"name": "中欣中部战区",
"children": [
{
"name": "金华",
"value": [119.64, 29.12]
}, {
"name": "西安",
"value": [108.95, 34.27]
}
]
},
{
"name": "中欣西部战区",
"children": [
{
"name": "成都",
"value": [104.06, 30.67]
}
]
}
]
async getData(){
// 这里获取的是散点图的数据
// 获取服务器的数据 对this.allData进行赋值之后 调用 updateChart 方法 更新图表
const {data:res} = await this.$http.get('map')
this.allData = res
this.updateChart()
},
updateChart(){
// 处理图表所需要的数据
// 按照请求过来的 数据结构 数组里面map操作出三组对象 对应三个级别
// 如果想要散点图 结合地图显示 要用到 配置 coordinateSystem:'geo'
const seriesArr = this.allData.map(item => {
return {
type: 'effectScatter',
rippleEffect: {
scale:5, // 涟漪的范围
brushType:'stroke' // 涟漪的效果 空心
},
name:item.name,
data:item.children,
coordinateSystem:'geo'
}
})
const legendArr = this.allData.map(item => {
return item.name
})
const dataOption = {
series:seriesArr,
legend:{
data:legendArr
}
}
this.chartsInstance.setOption(dataOption)
},
地图的点击事件(点击各个省份)
- 点击地图图表出发时间 根据事件对象.name 判断点击的是哪一个省份
- name 是英文 使用工具函数 转义下 返回 拼音和拼接的路径
- 根据这个路径请求 具体省份的数据(从静态资源中获取)转存到 this.mapData中 为图表实例再注册一个具体省份的地图 进行操作之前可以先判断缓存(this.mapData)中是否已经拥有如果有数据就可以使用缓存数据 减少请求次数
- 重新设置geo 替换map 并且解绑点击事件
async dblData(arg){
const provinceInfo = getProvinceMapInfo(arg.name)
// console.log(provinceInfo)
// 获取地图的矢量数据 重新设置下图表
// 判断当前点击这个省份是否存在 不存在再操作
if (!this.mapData[provinceInfo.key]){
const res2 = await axios.get('http://localhost:2904/' + provinceInfo.path)
// 请求过来的数据添加到 预留对象中 减少发送的请求
this.mapData[provinceInfo.key] = res2.data
this.$echarts.registerMap(provinceInfo.key,res2.data)
}
const changeOption = {
geo:{
map:provinceInfo.key
}
}
this.chartsInstance.setOption(changeOption)
this.chartsInstance.off('click',this.dblData)
},
getProvinceMapInfo工具函数:
const name2pinyin = {
安徽: 'anhui',
陕西: 'shanxi1',
澳门: 'aomen',
北京: 'beijing',
重庆: 'chongqing',
福建: 'fujian',
甘肃: 'gansu',
广东: 'guangdong',
广西: 'guangxi',
贵州: 'guizhou',
海南: 'hainan',
河北: 'hebei',
黑龙江: 'heilongjiang',
河南: 'henan',
湖北: 'hubei',
湖南: 'hunan',
江苏: 'jiangsu',
江西: 'jiangxi',
吉林: 'jilin',
辽宁: 'liaoning',
内蒙古: 'neimenggu',
宁夏: 'ningxia',
青海: 'qinghai',
山东: 'shandong',
上海: 'shanghai',
山西: 'shanxi',
四川: 'sichuan',
台湾: 'taiwan',
天津: 'tianjin',
香港: 'xianggang',
新疆: 'xinjiang',
西藏: 'xizang',
云南: 'yunnan',
浙江: 'zhejiang'
}
export function getProvinceMapInfo (arg) {
const path = `/static/map/province/${name2pinyin[arg]}.json`
return {
key: name2pinyin[arg],
path: path
}
}
双击再返回中国地图
- 为整个容器绑定双击事件
- 重新设置geo 替换map 并且添加点击事件
<template> <div class="comP2" ref="map_1" @dblclick="revertMap"></div> </template>
revertMap(){
const revertOption = {
geo:{
map:'china'
}
}
this.chartsInstance.setOption(revertOption)
this.chartsInstance.on('click',this.dblData)
}
图表跟随页面尺寸响应
每个图表基本一致 直接上代码
screenAdapter(){
const titleFontSize = this.$refs.map_1.offsetWidth / 100 * 3.6
const adapterOption = {
title:{
textStyle: {
fontSize: titleFontSize
}
},
legend: {
itemWidth: titleFontSize /2,
itemHeight: titleFontSize /2,
itemGap: titleFontSize/2,
textStyle: {
fontSize: titleFontSize / 2
}
}
}
this.chartsInstance.setOption(adapterOption)
this.chartsInstance.resize()
},
实例挂载到页面上时调用 离开页面时销毁
mounted() {
window.addEventListener('resize',this.screenAdapter)
this.screenAdapter()
},
destroyed() {
window.removeEventListener('resize',this.screenAdapter)
},