结对第二次作业—某次疫情统计可视化的实现

这个作业属于哪个课程 2020春|S班(福州大学)
这个作业要求在哪里 结对第二次作业
结对学号 221701336、221701331
这个作业的目标 某次疫情统计可视化的实现
作业正文 结对第二次作业博客
其他参考文献 《腾讯web代码规范》、Echarts官方文档及教程、CSDN

一、Github仓库与代码规范

二、成品展示


三、结对讨论

最开始我们讨论并学习了Echarts的用法

然后对是否使用爬虫技术获得数据进行了讨论

获得了json数据文件

需求讨论阶段



后续编码过程



四、设计实现

功能结构图

功能结构图

  • 数据部分
    • 此次实践的数据来自助教提供的文件,借助寒假第二次作业中实现的数据统计工具(进行了一些修改,并辅以手工调整),生成了上文第三部分中符合我们约定格式的json文件。由于纯前端无法方便的访问本地文件,我们把json格式的数据改写成js文件,这样页面就可以通过<script>标签直接访问数据。
    • 出于方便的考虑,我们用了两个工具函数getSpecifiedDatagetStatisticData(见下文第五部分)进行数据读取,提升了语义化。
  • 前端部分
    • 我们采用的是jQuery库原生html+css+js来编写网页。可视化的重任放在了优秀的图标库Echarts上,通过引入中国地图的china.js文件并在echarts的option.geo.map声明使用,实现了中国地图可视化部分的显示。有关可视化的细节请移步第五部分。
    • 以生成的中国地图作为首页,点击省份后跳转到该省份的趋势图页面。后来考虑到用户体验的问题,我们决定使用layer弹层,借助弹出窗口展示各省份的趋势图,优化用户操作的连贯性。
    • 用户可以通过切换时间查看不同时刻的疫情地图和统计数据,为此我们绑定了change/click事件,触发时自动取数据并更新到地图/趋势图上。得益于echarts可以异步加载或更新数据,这一过程还是比较轻松的。
    • 同样出于用户体验的考虑,在查看历史记录时,我们动态限制了比例尺的上限,避免了一个省份颜色太深而其他省份太浅的状况。
    • 最后完善样式和页面时,模仿了浏览器的标签页进行类型切换,并使用css3的transition,让切换变得更加平滑。
  • 后端&爬虫
    • 暂未实现

五、代码说明

首先是地图,主要还是依靠导入echarts.js以及China.js,然后对相应的类和属性注入数据

  • tooltip实现了鼠标悬浮在各省上,显示相应数据
  • visualMap则设置了页面左下角的颜色标注块的各项属性
  • geo设定了type为中国地图,并对各类缩放及文本格式进行设置
let option = {
    title: {
        text: '2020-02-02累计确诊情况地图'
    },
    tooltip: {
        formatter: function (params, ticket, callback) {
            return params.seriesName + '<br />' + params.name + ':' + params.value
        } //数据格式化
    },
    visualMap: {
        min: 0,
        max: 1500,
        left: 'left',
        top: 'bottom',
        text: ['高', '低'], //取值范围的文字
        inRange: {
            color: ['#ffffff', '#974236'] //取值范围的颜色
        },
        show: true //图注
    },
    geo: {
        map: 'china',
        roam: false, //不开启缩放和平移
        zoom: 1.23, //视角缩放比例
        label: {
            normal: {
                show: true,
                fontSize: '10',
                color: 'rgba(0,0,0,0.7)'
            }
        },
        itemStyle: {
            normal: {
                borderColor: 'rgba(0, 0, 0, 0.2)'
            },
            emphasis: {
                areaColor: '#F3B329', //鼠标选择区域颜色
                shadowOffsetX: 0,
                shadowOffsetY: 0,
                shadowBlur: 20,
                borderWidth: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
        }
    },
    series: [{
        name: '确诊人数',
        type: 'map',
        geoIndex: 0,
        data: dataList
    }]
}

这一部分则是实现了点击省份弹窗曲线图窗口

myChart.on('click', function (params) {
    console.log(params)
    const href = './province.html?province=' + params.data.name
    layer.open({
        type: 2,
        title: params.data.name + '省疫情详细情况',
        shadeClose: true,
        shade: 0.8,
        area: ['840px', '750px'],
        content: href 
      })
})

这是地图页面的时间选择部分,通过监听下拉菜单的选取事件,调用getSpecifiedData函数获取数据生成dataList并更新进echarts

$('#date-picker').on('change', e => {
    const newDate = e.target.value,
          type = $('.type-btn--active')[0].dataset.index
          typeText = $('.type-btn--active')[0].innerText
    dataList = provinces.map(provinceName => ({
        name: provinceName,
        value: getSpecifiedData(type, provinceName, newDate).infected
    }))
    option.series[0].data = dataList
    let max = Math.max(...dataList.map(v => v.value), 50)
    max = max > 2000 ? 2000 : max // 避免差异过大
    option.visualMap.max = max
    option.title.text = newDate + typeText + '情况地图'
    myChart.setOption(option)
})

通过该部分代码,在曲线图页面鼠标悬浮显示相应数据,重点是掌握param的各项参数,常用的包含有:

  • param.name:X轴的值
  • param.data:Y轴的值
  • param.value:Y轴的值
  • param.type:点击事件均为click
  • param.seriesName:legend的名称(即'累计确诊''新增确诊''累计治愈''累计死亡')
    tooltip: {
        trigger: 'axis',
        axisPointer: {
            type: 'cross',
            crossStyle: {
                color: '#999'
            }
        },
        formatter: function(params) {
            let html = params[0].name + '<br>'
            for (const param of params) {
                html += param.seriesName + '  ' + param.data + '<br>'
            }
            return html
        }
    },

曲线图数据分配

以湖北省新增感染为例:通过getStatisticData函数获得数据存储在augmentInfectedRecord里,并通过echarts的data属性获取数据

const augmentInfectedRecord = getStatisticData(2, 'infected', province)

    data = [{
        name: '新增确诊',
        type: 'line',
        data: augmentInfectedRecord
    },

两个用于读取数据的函数

/**
 * 获取指定类型、日期、省份的数据(无合法性校验)
 * @param {String|Number} scale 1:累计, 2:当日
 * @param {String} province 省份名,默认全国
 * @param {String} date YYYY-MM-DD格式的日期(某日或截至某日的数量),默认最新
 * @returns {Object}
 */
function getSpecifiedData (scale, province = '全国', date = '2020-02-02') {
    scale = scale == 1 ? 'aggregate' : 'augment'
    let result = {}
    const empty = {
        "infected": 0,
        "suspect": 0,
        "cure": 0,
        "death": 0
    }
    try {
        result = log[scale][date][province]
    } catch(e) {
        console.warn(e)
        result = empty
    }
    return result || empty
}

/**
 * 获取指定省份、类型的所有数据(无合法性校验)
 * @param {String|Number} scale 1:累计, 2:当日
 * @param {String} type 数据类型,infected|suspect|death|cure
 * @param {String} province 省份名,默认全国
 * @returns {Array}
 */
function getStatisticData (scale, type, province = '全国') {
    scale = scale == 1 ? 'aggregate' : 'augment'
    let result = []
    Object.values(log[scale]).forEach(day => {
        if (day[province]) {
            result.push(day[province][type])
        } else {
            result.push(0)
        }
    })
    return result
}

统计数据的格式

const log = Object.freeze({
    "aggregate": {
        "2020-01-19": {
            "广东": {
                "infected": 1,
                "suspect": 0,
                "cure": 0,
                "death": 0
            },
            ...
        },
        ...
    }
    "augment": {...}
}

六、心路历程和收获&评价结对队友

  • 心路历程和收获:一个全靠echarts支撑起的项目。echarts是个非常牛x的工具,用它可以非常方便地画图表,感谢开发团队为前端领域做出的贡献。
  • 评价结对队友:积极主动,阻止了我继续摸鱼下去的念头。配合高效、紧密,沟通顺畅,合作起来十分愉快。希望能选个专精的方向加大力度,也希望下次能继续深入合作,奥里给!
posted @ 2020-03-16 21:39  ldc-37  阅读(235)  评论(0编辑  收藏  举报