vue+echarts项目五:商家分布(地图+散点图)

22 篇文章 2 订阅

 效果如图所示

组件环境准备:

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()
    },

显示地图

  1. 获取中国地图矢量数据(这里的中国地图属性是直接从public/static静态文件拿到的) 
  2. 注册地图数据到 全局echarts对象
  3. 配置 geo
  4. 在地图实例渲染出来之后 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)
      },

地图的点击事件(点击各个省份)

  1. 点击地图图表出发时间 根据事件对象.name 判断点击的是哪一个省份
  2. name 是英文 使用工具函数 转义下 返回 拼音和拼接的路径
  3. 根据这个路径请求 具体省份的数据(从静态资源中获取)转存到 this.mapData中 为图表实例再注册一个具体省份的地图   进行操作之前可以先判断缓存(this.mapData)中是否已经拥有如果有数据就可以使用缓存数据 减少请求次数
  4. 重新设置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
  }
}

双击再返回中国地图

  1. 为整个容器绑定双击事件
  2. 重新设置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)
    },

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值