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


    这个作业属于哪个课程 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中国地图的导入,曲线图的导入,各个图表type的各属性用法,然后还学习了后面相关的一些前端的知识。由于不是很懂json文件的数据是如何导出的,也学习了一下。我们组讨论的比较早,但是由于手头都还有作业,前期只是进行了知识的储备,算是比较晚开工的,之前我做了页面demo,编写了代码规范,一起跟队友讨论了具体需求。后续确定路线后才开工。

    我的队友是个西二的前端大佬,很靠谱,也很让人安心。我的代码比较差,前端简单做做两个页面的demo,将图表框架建立起来,然后学习了他的代码后敲了些数据传输和样式表的内容。因为我个人也是偏向于学习前端的技术,这次实践从他那学到了很多。

  • 相关阅读:
    C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)
    c#串口通信类代码可以直接调用
    栈的理解以及如何计算程序所需栈的大小并在IAR中设置栈
    Heap堆的理解以及在IAR中如何设置堆的大小
    ARM Cortex-M0权威指南高清中文版pdf免费分享下载
    如何重新划分linux分区大小
    Using Internal EEPROM of PIC Microcontroller
    树莓派Odroid等卡片式电脑上搭建NAS教程系列6-miniDLNA
    './mysql-bin.index' not found (Errcode: 13) 的解决方法
    移植mysql到嵌入式ARM平台
  • 原文地址:https://www.cnblogs.com/hqq1031196651/p/12492470.html
Copyright © 2020-2023  润新知