【Vue】疫情实时数据及地图 Vue + Echarts + vxeTable

血红的双手。 提交于 2020-03-05 01:01:31

本期内容

使用 Vue + Echarts + vxeTable 搭建前端展示界面,接口请求示例是腾讯肺炎疫情实时动态页面中的开放接口

知识基础

如何在 Vue 中引入 Echarts,点这里

如何在 Vue 中引入 vxeTable,点这里


 

部分效果

国家和地区数据
我国省份数据​​

一、申请百度地图 ak 以使用 Echarts 地图

1、申请 ak

① 进入 http://lbsyun.baidu.com/

② 登录后点击 控制台

③ 按要求操作后,点击申请 密钥

④选择 浏览器端

⑤保存好 ak

2、创建 map.js 文件调用 BMap

① 建立 map.js 文件

② 在 map.js 中将申请的 ak 填入下方函数中

export function MP () {
    const ak = '...' // 这里填的是你自己的 ak
    return new Promise(function (resolve, reject) {
        window.init = function () {
            resolve(BMap)
        }
        var script = document.createElement('script')
        script.type = 'text/javascript'
        script.src = `http://api.map.baidu.com/api?v=2.0&ak=${ak}&callback=init`
        script.onerror = reject
        document.head.appendChild(script)
    })
}

③ 在需要调用地图的 vue 页面的 js 中引入,并声明 bmap

import { MP } from '../map.js'
require('echarts/extension/bmap/bmap')

二、引入 Echarts 中对应的地图插件(完整代码)

下列代码中每块函数的功能都有注释,值得注意的几点:

① api 是因为跨域问题,具体解决方法可以参考这篇文章

// 此处的 api 是通过配置跨域,将原本的 url 替换成 api 来表示
const url = `/api/g2/getOnsInfo?name=disease_h5&callback=&_=${timeStamp}`

② geoCoordMap:各省会经纬度

③ 页面中调用了 定时器 以实现固定时间刷新页面

④ option 中的内容均为 Echarts 文档中的图表写法,若用其他图表可以参考官方文档代码写法

完整代码如下

<!-- Description:肺炎疫情地图 -->
<template>
  <div>
    <div>现在时间:{{timeNow}}</div>
    <div>刷新次数:{{timeCount}}</div>
    <vxe-table :data="countryData" align="center" stripe>
      <vxe-table-column type="seq" title="序号" width="80"></vxe-table-column>
      <vxe-table-column field="name" title="国家"></vxe-table-column>
      <vxe-table-column field="total.confirm" title="确诊人数"></vxe-table-column>
      <vxe-table-column field="total.suspect" title="疑似病例"></vxe-table-column>
      <vxe-table-column field="total.heal" title="治愈人数"></vxe-table-column>
      <vxe-table-column field="total.dead" title="死亡人数"></vxe-table-column>
    </vxe-table>
    <div style="height:100px"></div>
    <vxe-table :data="provinceData" align="center" stripe>
      <vxe-table-column type="seq" title="序号" width="80"></vxe-table-column>
      <vxe-table-column field="name" title="省份"></vxe-table-column>
      <vxe-table-column field="total.confirm" title="确诊人数"></vxe-table-column>
      <vxe-table-column field="total.suspect" title="疑似病例"></vxe-table-column>
      <vxe-table-column field="total.heal" title="治愈人数"></vxe-table-column>
      <vxe-table-column field="total.dead" title="死亡人数"></vxe-table-column>
    </vxe-table>
    <div style="height:100px"></div>
    <div style="height:900px" id="main"></div>
  </div>
</template>

<script>
import { MP } from '../map.js'
require('echarts/extension/bmap/bmap')
export default {
  data () {
    return {
      provinceData: null,
      countryData: null,

      timeNow: new Date(),
      timeCount: 0,

      echartsDatas: [],
      temp: {},

      // convertData: null,
      geoCoordMap: {
        '山东': [117.000923, 36.675807],
        '河北': [115.48333, 38.03333],
        '吉林': [125.35000, 43.88333],
        '黑龙江': [127.63333, 47.75000],
        '辽宁': [123.38333, 41.80000],
        '内蒙古': [111.670801, 41.818311],
        '新疆': [87.68333, 43.76667],
        '甘肃': [103.73333, 36.03333],
        '宁夏': [106.26667, 37.46667],
        '山西': [112.53333, 37.86667],
        '陕西': [108.95000, 34.26667],
        '河南': [113.65000, 34.76667],
        '安徽': [117.283042, 31.86119],
        '江苏': [119.78333, 32.05000],
        '浙江': [120.20000, 30.26667],
        '福建': [118.30000, 26.08333],
        '广东': [113.23333, 23.16667],
        '江西': [115.90000, 28.68333],
        '海南': [110.35000, 20.01667],
        '广西': [108.320004, 22.82402],
        '贵州': [106.71667, 26.56667],
        '湖南': [113.00000, 28.21667],
        '湖北': [114.298572, 30.584355],
        '四川': [104.06667, 30.66667],
        '云南': [102.73333, 25.05000],
        '西藏': [91.00000, 30.60000],
        '青海': [96.75000, 36.56667],
        '天津': [117.20000, 39.13333],
        '上海': [121.55333, 31.20000],
        '重庆': [106.45000, 29.56667],
        '北京': [116.41667, 39.91667],
        '台湾': [121.30, 25.03],
        '香港': [114.10000, 22.20000],
        '澳门': [113.50000, 22.20000]
      }
    }
  },
  created () {
    this.getInfo()
  },
  mounted () {
    // 调用实时刷新的方法
    this.time()
    this.$nextTick(() => {
      MP().then(BMap => {
        this.drawChart()
      })
    })
  },
  destroyed () {
    // 销毁时关闭时间器
    clearInterval(this.timer)
  },
  methods: {
    // 获取武汉疫情信息
    getInfo () {
      const timeStamp = new Date().getTime()
      // 此处的 api 是通过配置跨域,将原本的 url 替换成 api 来表示
      const url = `/api/g2/getOnsInfo?name=disease_h5&callback=&_=${timeStamp}`
      this.$http.get(url).then(res => {
        // 用 JSON.parse 转换成 json 格式的数据
        const subData = JSON.parse(res.data.data)
        // areaTree 取 0 为中国,其他国家需递增
        // ------省份数据------
        const china = subData.areaTree[0]
        this.provinceData = china.children
        // ------国家数据------
        this.countryData = subData.areaTree

        for (var i = 0; i < this.provinceData.length; i++) {
          this.temp.name = this.provinceData[i].name
          this.temp.value = this.provinceData[i].total.confirm
          this.echartsDatas.push(this.temp)
          this.temp = {}
        }
        this.drawChart()
      }).catch(err => {
        console.log(err)
      })
    },
    // 定时刷新,发起请求, 1800000 为毫秒,即为半小时刷新一次
    time () {
      if (this.timer) {
        clearInterval(this.timer)
      } else {
        this.timer = setInterval(() => {
          this.timeNow = new Date()
          this.timeCount += 1
          this.getInfo()
        }, 300000)
      }
    },

    /**
     * 画echarts
     */

    drawChart () {
      var convertData = (echartsDatas) => {
        var res = []
        // console.log('res1', res)
        // console.log('echartsDatas', echartsDatas)
        for (var i = 0; i < echartsDatas.length; i++) {
          var geoCoord = this.geoCoordMap[echartsDatas[i].name]
          // console.log('geoCoord:', geoCoord)

          if (geoCoord) {
            res.push({
              name: echartsDatas[i].name,
              value: geoCoord.concat(echartsDatas[i].value)
            })
          }
        }
        return res
      }

      var echarts = require('echarts')
      var myChart = echarts.init(document.getElementById('main'))
      
      // 指定图表的配置项和数据
      var option = {
        backgroundColor: 'transparent',
        title: {
          text: '新型肺炎疫情实时动态',
          subtext: 'Data from news',
          left: 'center',
          textStyle: {
            color: '#fff'
          }
        },
        tooltip: {
          trigger: 'item',
          formatter: (obj) => {
            var str = ''
            str = '确诊人数</br>' + obj.data.name + ':&nbsp' + obj.data.value[2]
            return str
          }
        },
        bmap: {
          // 首次呈现的地理位置
          center: [104.114129, 37.550339],
          // zoom:放大倍数
          zoom: 5,
          // roam:是否可以拖动地图
          roam: false,
          mapStyle: {
            styleJson: [
              {
                'featureType': 'water',
                'elementType': 'all',
                'stylers': {
                  'color': '#044161'
                }
              },
              {
                'featureType': 'land',
                'elementType': 'all',
                'stylers': {
                  'color': '#004981'
                }
              },
              // 我国边界线颜色
              {
                'featureType': 'boundary',
                'elementType': 'geometry',
                'stylers': {
                  'color': 'fff'
                }
              },
              {
                'featureType': 'railway',
                'elementType': 'all',
                'stylers': {
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'highway',
                'elementType': 'geometry',
                'stylers': {
                  'color': '#004981'
                }
              },
              {
                'featureType': 'highway',
                'elementType': 'geometry.fill',
                'stylers': {
                  'color': '#005b96',
                  'lightness': 1
                }
              },
              {
                'featureType': 'highway',
                'elementType': 'labels',
                'stylers': {
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'arterial',
                'elementType': 'geometry',
                'stylers': {
                  'color': '#004981'
                }
              },
              {
                'featureType': 'arterial',
                'elementType': 'geometry.fill',
                'stylers': {
                  'color': '#00508b'
                }
              },
              {
                'featureType': 'poi',
                'elementType': 'all',
                'stylers': {
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'green',
                'elementType': 'all',
                'stylers': {
                  'color': '#056197',
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'subway',
                'elementType': 'all',
                'stylers': {
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'manmade',
                'elementType': 'all',
                'stylers': {
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'local',
                'elementType': 'all',
                'stylers': {
                  'visibility': 'off'
                }
              },
              {
                'featureType': 'arterial',
                'elementType': 'labels',
                'stylers': {
                  'visibility': 'off'
                }
              },
              // 所有国边界线
              {
                'featureType': 'boundary',
                'elementType': 'geometry.fill',
                'stylers': {
                  'color': '#029fd4'
                }
              },
              {
                'featureType': 'building',
                'elementType': 'all',
                'stylers': {
                  'color': '#1a5787'
                }
              },
              {
                'featureType': 'label',
                'elementType': 'all',
                'stylers': {
                  'visibility': 'off'
                }
              }
            ]
          }
        },
        series: [
          {
            name: '确诊人数',
            // type:圆点的样式
            type: 'effectScatter',
            coordinateSystem: 'bmap',
            // 0-6 即为排名前六,sort 为排序
            data: convertData(this.echartsDatas.sort(function (a, b) {
              return b.value - a.value
            }).slice(0, 35)),
            symbolSize: 20,
            // 小圆点是否有“范围圈”
            showEffectOn: 'emphasis',
            rippleEffect: {
              brushType: 'stroke'
            },
            // 控制圆点在 hover 的时候是否变大
            hoverAnimation: true,
            label: {
              formatter: '{b}',
              position: 'right',
              show: true
            },
            // 大圆点颜色
            // shadowcolor 圆点阴影颜色
            itemStyle: {
              color: '#f4e925',
              shadowBlur: 10,
              shadowColor: '#fff'
            },
            zlevel: 1
          }
        ]
      }
      // 使用刚指定的配置项和数据显示图表。
      myChart.setOption(option)
    }
  }
}
</script>

<style scoped>
</style>

三、过程中遇到的问题

1、如何往结构体数组中加入二级数组

如:要将多个 temp{name:' ',value:' '} 添加到 echartsDatas[ ] 中

解决方法如下:记得用完 temp 后将其清空!否则数组会无限叠加。

2、原生地图代码中,对应各地的 value 出不来,只显示经纬度的 “经度”

原因:官方提供的图表代码中,只能获取到经纬度数组中的 arr[0] 的数据,即经度

思路:在数据中,value 和经纬度的数据合并在一起了,因此尝试在formatter中加入function来获取数据展示

解决方法:在 tooltip 中写入 formatter 的函数即可

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!