美文网首页
如果让你展示国内各省市疫情数据你会怎么做

如果让你展示国内各省市疫情数据你会怎么做

作者: 不讨喜的大雄 | 来源:发表于2020-04-09 00:49 被阅读0次

    2020 年初始至今,冠状病毒肆虐,好在国内疫情已经逐步减少,武汉也解封了,而国外疫情却日益严重,不容乐观。

    做个可视化地图模拟展示一下疫情

    我们可以看到,各大 APP 都有实时显示全国乃至世界的疫情数据的地图表,那么它们是如何实现的呢?

    让我们以中国为例,实现一下展示效果。由于平时用 Vue 较多,可视化框架之前在项目中用过 echarts,就用这两个来演示。(注:本次数据都是随机生成,非官方真实数据)

    用 vue-cli 快速搭建

    vue create vue-echarts-map-china
    

    引入 echarts

    yarn add echarts -D 
    

    如何展示中国各省数据

    ProvinceChart.vue

    <template>
      <div class="chart" ref="chart" style="width: 100%; height: 800px"></div>
    </template>
    

    我们首先需要给 echarts 一个容器

    引用 js/json 地图数据

    echats 内置了 china.js 和 china.json 及其省市地图包,china.js 引入即可使用 china.json 需要注册到 echarts,两种方式任选

    import echarts from "echarts";
    import "echarts/theme/macarons"; // echarts 主题
    
    // 1. china.js 直接使用
    import china from "echarts/map/js/china";
    
    // 2. china.json 需注册
    import china from "echarts/map/json/china";
    echarts.registerMap("china", china);
    

    主要结构

    export default {
      name: "chart",
      data() {
        return {
          chart: null
        };
      },
      mounted() {
        if (!this.chart) {
          this.drawChinaMap();
        }
      },
      beforeDestroy() {
        if (!this.chart) {
          return;
        }
        this.chart.dispose();
        this.chart = null;
      },
      methods: {
        drawChinaMap(){
          ...
        }
      }
    };
    

    drawChinaMap 方法详解

    首先找到我们的容器用 echarts.init() 初始化 echarts

    this.chart = echarts.init(document.querySelector(".chart"), "macarons");
    this.chart.setOption({
      ...
    })
    

    通过 setOption 传入我们需要设定的选项参数

    图表类型及参数

    最主要的是设置图表类型了

    series: [
      {
        name: "数据",
        type: "map",
        mapType: "china", // 对应我们注册好的 "china"
        roam: true, // 是否可缩放
        label: { // 文本标签
          normal: {
            show: true //省份名称
          },
          emphasis: {
            show: false
          }
        },
        // 地图默认样式
        itemStyle: {
          normal: {
            show: true,
            areaColor: "#CECECE",
            borderColor: "#FCFCFC",
            borderWidth: "1"
          },
          emphasis: {
            show: true,
            areaColor: "#C8A5DF"
          }
        },
        data: [
          ...
        ]
      }
    ]
    

    最重要的是 34 个省份的数据,这里我们模拟一下(注意格式和 name 是固定的)

    data: [
      { name: "北京", value: Math.round(Math.random() * 1000) },
      { name: "天津", value: Math.round(Math.random() * 1000) },
      { name: "上海", value: Math.round(Math.random() * 1000) },
      { name: "重庆", value: Math.round(Math.random() * 1000) },
      { name: "河北", value: Math.round(Math.random() * 1000) },
      { name: "河南", value: Math.round(Math.random() * 1000) },
      { name: "云南", value: Math.round(Math.random() * 1000) },
      { name: "辽宁", value: Math.round(Math.random() * 1000) },
      { name: "黑龙江", value: Math.round(Math.random() * 1000) },
      { name: "湖南", value: Math.round(Math.random() * 1000) },
      { name: "安徽", value: Math.round(Math.random() * 1000) },
      { name: "山东", value: Math.round(Math.random() * 1000) },
      { name: "新疆", value: Math.round(Math.random() * 1000) },
      { name: "江苏", value: Math.round(Math.random() * 1000) },
      { name: "浙江", value: Math.round(Math.random() * 1000) },
      { name: "江西", value: Math.round(Math.random() * 1000) },
      { name: "湖北", value: 9999 },
      { name: "广西", value: Math.round(Math.random() * 1000) },
      { name: "甘肃", value: Math.round(Math.random() * 1000) },
      { name: "山西", value: Math.round(Math.random() * 1000) },
      { name: "内蒙古", value: Math.round(Math.random() * 1000) },
      { name: "陕西", value: Math.round(Math.random() * 1000) },
      { name: "吉林", value: Math.round(Math.random() * 1000) },
      { name: "福建", value: Math.round(Math.random() * 1000) },
      { name: "贵州", value: Math.round(Math.random() * 1000) },
      { name: "广东", value: Math.round(Math.random() * 1000) },
      { name: "青海", value: Math.round(Math.random() * 1000) },
      { name: "西藏", value: Math.round(Math.random() * 1000) },
      { name: "四川", value: Math.round(Math.random() * 1000) },
      { name: "宁夏", value: Math.round(Math.random() * 1000) },
      { name: "海南", value: Math.round(Math.random() * 1000) },
      { name: "台湾", value: Math.round(Math.random() * 1000) },
      { name: "香港", value: Math.round(Math.random() * 1000) },
      { name: "澳门", value: Math.round(Math.random() * 1000) }
    ] //数据
    

    其他选项设置

    backgroundColor: "#FFFFFF",
    title: {
      text: "全国省市地图大数据",
      subtext: "虚构数据",
      x: "center"
    },
    tooltip: {
      trigger: "item"
    },
    toolbox: { // 右侧复位下载
      show: true,
      orient: "vertical",
      right: "20",
      top: "center",
      feature: {
        mark: { show: true },
        restore: { show: true },
        saveAsImage: { show: true }
      }
    },
    
    // 左侧小导航图标
    visualMap: {
      show: true,
      x: "left",
      y: "center",
      splitList: [
        { start: 10000 },
        { start: 1000, end: 9999 },
        { start: 500, end: 999 },
        { start: 100, end: 499 },
        { start: 10, end: 99 },
        { start: 0, end: 9 }
      ],
      color: [
        "#a50026",
        "#d73027",
        "#f46d43",
        "#fdae61",
        "#fee090",
        "#ffffbf",
        "#f0f0f0"
      ]
    },
    

    效果如下:

    如何展示中国各市数据

    如果要展示各市单独数据较为简单,只需要把地图和对应数据变成省即可

    import hubei from "echarts/map/json/province/hubei";
    echarts.registerMap("hubei", hubei);
    
    series:[
      ...
      mapType: "hubei",
      ...
    ]
    

    你还可以做到点击省切换成市的效果,网上也有相应教程,实现方法也简单,这里不作详细介绍。

    但是我想要看整个中国地图下的市的疫情情况怎么办?

    合并省市地图

    由于官方只提供了中国地图和省市分开的地图 json 或 js 包,而没有合并在一起的,我们没有现成的数据。

    然而我注意到,china 和各省的 json 包只是 features 不同,如下图所示:

    china.features = [...new Set([...china.features, ...hubei.features])];
    

    最终,这种方法被我放弃了,原因如下:

    1. 视觉效果差:

    如下图,有字根本看不清,没字也会很密集

    1. 渲染效果差:

    目前只实现了一个省,可预见的是加上所有省份数据量很大(features 长度最终会是 533 ),渲染会卡顿

    1. 有引入延迟问题:

    由于需要将 34 个省 JSON 包分别引入后合并到 china 内部,通常 echarts 组件已经渲染完毕

    使用中国地图配合市散点图

    我找到官方提供的scatter-visualMap-piecewise示例,感觉这种方式也能满足我的要求,且呈现效果更好

    选项变化

    与原选项主要区别是 series 使用 scatter 散点类型,同时引入 geo 地理坐标系组件

    geo: {
      map: "china",
      roam: true,
      itemStyle: {
        // 定义样式
        normal: {
          // 普通状态下的样式
          areaColor: "#323c48",
          borderColor: "#111"
        },
        emphasis: {
          // 高亮状态下的样式
          areaColor: "#2a333d"
        }
      }
    },
    series: [
      {
        name: "确诊人数",
        symbolSize: 10, // 点坐标大小
        type: "scatter",
        data: this.cityData,
        coordinateSystem: "geo"
      }
    ]
    

    其数据格式如下

    // this.cityData
    {
      ...
      { name: "武汉", value: [114.31, 30.52, 8888 }], // { name: name, value: [x, y, value}],
      { name: "大庆", value: [125.03, 46.58, Math.round(Math.random() * 100) }]
    }
    

    示例小问题

    需要注意的是,官方示例中 tooltip 的悬浮数据是有问题的,它不是 pm2.5 的 value,而是极坐标的 Y 的值

    想要其展示正确的数据需要在 tooltip 设置 formatter:以回调函数格式设置数据为 data 的第三个数据

    tooltip: {
      trigger: "item",
      formatter: params => {
        return (
          params.seriesName + "<br/>" + params.name + ":" + params.data.value[2]
        );
      }
    }
    

    另外,示例中 geo 数据也是不完整的,可通过 datav 获取完整中国 geo 数据。

    最终效果如下:

    总结

    至此,我们完成了国内各省市疫情模拟数据的可视化,如果想要展示世界数据也是类似,只需找到相应地图包替换,并处理对应数据即可。echarts 提供了完整的文档,按需查找对应选项即可完成相应需求,当然还有很多不错的库和方法等我们去探究。

    如需查看完整代码:请点这里

    看到这里了,不点个赞吗😄!

    相关文章

      网友评论

          本文标题:如果让你展示国内各省市疫情数据你会怎么做

          本文链接:https://www.haomeiwen.com/subject/kzvzuhtx.html