全国疫情可视化动态分析-[原力计划]

全国疫情可视化动态分析-[原力计划]


前言

最近大家都在关注疫情多久才能够被胜。今天带大家来 <全国疫情可视化动态分析>

全文是在丁香医生的数据下,增加周边城市的疫情情况。

今天我们通过可视化为大家提供各种疫情相关的进展,希望能够帮助大家更好理解现在疫情的情况。

先来看下成品图:

热力地图

大图看的有点乱,我们放大一点看看

1.我根据中国不同的省份,根据不同人数显示不同的颜色,鼠标移动会显示当前疫情。

放大的热力地图

各地区颜色可通过左方修改:上下有两个箭头可以上拉下拉,选取区域,如下图:

2.当地图放大后,可以看到更多的细节,
比如说如果数量达到100后让当前位置,加入警报,当然随着数量越多该位置的点更大、且冒泡提升更大。

放大后效果如下图:

本博客只介绍思路,项目开源 —CSDN原力计划.


1.正文

1.第一步获取数据

下面附上最新最全面的API [开源]

HttpClient httpClient = new HttpClient { BaseAddress = new Uri("https://view.inews.qq.com/") };
HttpResponseMessage httpResponseMessage = httpClient.GetAsync("g2/getOnsInfo?name=disease_h5").GetAwaiter().GetResult();
var result = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
nCoVData data = JsonConvert.DeserializeObject<nCoVData>(result);
nCoVDataDetail nCoVDataDetail = JsonConvert.DeserializeObject<nCoVDataDetail>(data.Data);

将json解析成c# 对象。

nCoVDataDetail.AreaTree #各省份信息

数量较多不展示图片了

public class AreaTree
{
    public AreaTree()
    {
        this.Today = new Today();
        this.Total = new Overview();
        this.Children = new List<Children>();
    }
       //国家名字
    public string Name { get; set; }
        //今天的变化情况
    public Today Today { get; set; }
        //总数量
    public Overview Total { get; set; }
        //省或者直辖市
    public List<Children> Children { get; set; }
}

public class Children
{
     //省名或者直辖市名
    public string Name { get; set; }

    // 今日变化
    public Today Today { get; set; }
    // 统计
    public Overview Total { get; set; }
        //省下面的区,直辖市下面的区
    public List<Children> children { get; set; }
}

模板类似上面的

.
.


2.第二步获取经纬度

利用百度地图API 获取定位信息

private static mapv3 GetHttpRequest(string areaAddress)
{
    HttpClient httpClient = new HttpClient { BaseAddress = new Uri("http://api.map.baidu.com/") };
    HttpResponseMessage httpResponseMessage = httpClient.GetAsync("geocoding/v3/?address=" + areaAddress + "&output=json&ak=你的key").GetAwaiter().GetResult();
    var result = httpResponseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    mapv3 data = JsonConvert.DeserializeObject<mapv3>(result);
    return data;
}

百度地图API开发文档:https://lbsyun.baidu.com/

百度地图注册你的获取应用key

mapv3模型,在这里我只介绍用到的经纬度

public class mapv3
{
    public int status { get; set; }

    public result result { get; set; }
}

status 返回为状态0 成功 其余都失败

看下result

public class result
{
    public location location { get; set; }

    public int precise { get; set; }

    public int confidence { get; set; }

    public int comprehension { get; set; }

    public string level { get; set; }
}

其他不介绍了,详细看官网,在这里只介绍location。

public class location
{
    public double lng { get; set; }

    public double lat { get; set; }

}

以上就获取到经纬度了

.
.


3.第三步可视化分析

整理数据与echarts数据格式相对应

echarts经纬度格式:

{
	"位置":[,]
}

经纬度地址需要数组存取。

private static Dictionary<string, double[]> dic = new Dictionary<string, double[]>();

我使用dictionary,鉴别是否已经存在,方便查询,减少浪费资源。

下面是整体格式化:

private static void GetPositionOfJson(IList<AreaTree> areaTrees)
{
    // 考虑到查询成本
    echartsModels = new List<EchartsModel>();
    echartsMapModels = new List<EchartsMapModel>();
    pronvincedic =new List<EchartsModel>();
    EchartsModel echartsModel = new EchartsModel();
    EchartsMapModel echartsMapModel = new EchartsMapModel();
    foreach (var country in areaTrees)
    {
        var CountryName = country.Name;
        if (CountryName != "中国")
        {
            //only china 其他国家不管
            continue;
        }
        var provinceRank = "省";
        foreach (var province in country.Children)
        {
            if (province.Name == "北京" || province.Name == "天津" || province.Name == "上海" || province.Name == "重庆")
            {
                provinceRank = "市";
            }
            var provinceName = province.Name + provinceRank;

            //加入统计 因为西藏省区
            if (!dic.Keys.Contains(province.Name))
            {
                var fullName = provinceName + province.Name;
                mapv3 mapv3 = GetHttpRequest(fullName);
                if (mapv3.status == 0)
                {
                    var location = mapv3.result.location;
                    double[] d = new double[] { location.lng, location.lat };
                    dic.Add(province.Name, d);
                }
            }
            EchartsModel echartsModelPClone = (EchartsModel)echartsModel.clone();
            echartsModelPClone.name = province.Name;
            echartsModelPClone.value = province.Total.Confirm;
            pronvincedic.Add(echartsModelPClone);


            //颜色
            EchartsMapModel echartsMapModelClone = (EchartsMapModel)echartsMapModel.clone();
            echartsMapModelClone.name = province.Name;
            //总感染人数
            EchartsModel InfectSum = (EchartsModel)echartsModel.clone();
            InfectSum.name = "感染人数";
            InfectSum.value = province.Total.Confirm;
            //治愈人数
            EchartsModel CureSum = (EchartsModel)echartsModel.clone();
            CureSum.name = "治愈人数";
            CureSum.value = province.Total.Heal;
            //沉重的死亡人数
            EchartsModel HeadSum = (EchartsModel)echartsModel.clone();
            HeadSum.name = "死亡人数";
            HeadSum.value = province.Total.Dead;
            List<EchartsModel> echartsModelMapList = new List<EchartsModel>();
            echartsModelMapList.Add(InfectSum);
            echartsModelMapList.Add(CureSum);
            echartsModelMapList.Add(HeadSum);
            echartsMapModelClone.value = echartsModelMapList;
            echartsMapModels.Add(echartsMapModelClone);
            foreach (var city in province.children)
            {
                if (!dic.Keys.Contains(city.Name))
                {
                    var fullName = provinceName + city.Name;
                    mapv3 mapv3 = GetHttpRequest(fullName);
                    if (mapv3.status == 0)
                    {
                        var location = mapv3.result.location;
                        double[] d = new double[] { location.lng, location.lat  };
                        dic.Add(city.Name, d);
                    }
                }
                //后续需要优化部分
                EchartsModel echartsModelClone= (EchartsModel)echartsModel.clone();
                echartsModelClone.name = city.Name;
                echartsModelClone.value = city.Total.Confirm;
                echartsModels.Add(echartsModelClone);
            }
        }
    }
}

分析下:

加上下面的经纬度:

foreach (var city in province.children)
{
    if (!dic.Keys.Contains(city.Name))
    {
        var fullName = provinceName + city.Name;
        mapv3 mapv3 = GetHttpRequest(fullName);
        if (mapv3.status == 0)
        {
            var location = mapv3.result.location;
            double[] d = new double[] { location.lng, location.lat  };
            dic.Add(city.Name, d);
        }
    }
    //后续需要优化部分
    EchartsModel echartsModelClone= (EchartsModel)echartsModel.clone();
    echartsModelClone.name = city.Name;
    echartsModelClone.value = city.Total.Confirm;
    echartsModels.Add(echartsModelClone);
}

判断不存在,通过百度查询。

EchartsModel 是传递echarts模型中的散点格式。

echarts格式是{name:"",value:""},散点显示数字和名字。

因为每个城市创建数量过多,所以我采用克隆的方式进行处理。

有一个地方需要介绍下:

if (province.Name == "北京" || province.Name == "天津" || province.Name == "上海" || province.Name == "重庆")
{
    provinceRank = "市";
}

由于这几个是直辖市 通过市可以直接定位

如果加上省份反而不准确
.
.


4.第四步数据存储

把经纬度,保存在字典中,每次重启的时候需要查询一次,这非常耗时

解决方案:查询的数据保存为json格式,存入本地、重启后先读取。

且启动的时候要初始化,数据必须动态更新,所以每隔1h更新数据。

timer.LoadMap();
//初始化
timer.getData(null,null);
//每隔一小时执行一次
System.Timers.Timer  timerOneHour= new System.Timers.Timer(60 * 60 * 1000);
timerOneHour.Elapsed += new System.Timers.ElapsedEventHandler(timer.getData);
timerOneHour.AutoReset = true;

.
.


5.第五步数据渲染

颜色和大小

visualMap: {
    show: true,
    min: 0,
    max: 2000,
    left: 'left',
    top: 'bottom',
    text: ['高', '低'], // 文本,默认为数值文本
    calculable: true,
    seriesIndex: [1],
    pieces: [{
    }],
    inRange: {
        color: ["#F2FE96",'#FFFF00', '#A5CC82',"#BF444C"], // 绿到黄到红    
    }
}

设定省份的数量区间是0-2000,颜色在这区间变动 :

color: ["#F2FE96",'#FFFF00', '#A5CC82',"#BF444C"]

散点和气泡大小:

symbolSize: function (val) {
    num = val[2] / 5;
    num = num > 50 ? 50 : num;
    num = num < 10 ? 10 : num;
    return num;
}

最大为50,最小为10。

下面是如果value>100,那么让它显示危险标志。

{
    name: 'item>100',
    type: 'effectScatter',
    coordinateSystem: 'geo',
    data: convertData(data.sort(function (a, b) {
        return b.value - a.value;
    }).filter(function (item) {
        return item.value >= 100
    })
    )
    ,
    symbolSize: function (val) {
        num = (val[2] / 10);
        num = num > 50 ? 50 : num
        if (val[2] == 0) {
            num = 0;
        }
        return num;
    },
    showEffectOn: 'render',
    rippleEffect: {
        brushType: 'stroke'
    },
    hoverAnimation: true,
    label: {
        normal: {
            formatter: '{b}',
            position: 'right',
            show: false
        }
    },
    itemStyle: {
        normal: {
            color: 'red',
            shadowBlur: 10,
            shadowColor: 'red'
        }
    },
    zlevel: 1
}

.
.


希望疫情快点结束,带好口罩,保护自己,保护他人,为社会作贡献。

码云开源地址:https://gitee.com/xingly-cn/wuhan

欢迎各位大佬,加入完善,为社区做贡献!

发布了60 篇原创文章 · 获赞 83 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/xg987599519/article/details/104433738