基于 HTML + WebGL 结合 23D 的疫情地图实时大屏 PC 版【转载】

前言

2019年12月以来,湖北省武汉市陆续发现了多例肺炎病例,现已证明为一种新型冠状病毒感染引发的急性呼吸道传染病并蔓延全国,肺炎疫情牵动人心,人们天天起来第一件事变成了关注疫情进展,指望这场天灾早日结束,社会回归正常秩序。不久前在前端小伙伴和设计小伙伴的合做下咱们推出了移动版疫情地图GIS版疫情地图,而此次咱们又推出了 PC 版的疫情地图,浅色系的色调搭配 2D,3D 的方式综合展现疫情的最新动态和历史数据,但愿能给你们带来一点比较愉悦的观感体验,减轻下焦虑。html

先打开页面感觉一下:

点击预览前端

还有 GIS 版的预览:

GIS 版可在上方导航栏内点击打开,想单独打开能够点击 GIS版疫情地图node

数据源说明

CDC, 百度,腾讯,丁香园都有本身的疫情地图,咱们的数据也来源于此,这部分在以前的文章《HTML5 WebGL 实现 3D 地图助力新型冠状病毒疫情实时数据可视化》有详细说明,就再也不赘述了。浏览器

系统介绍

数据展现部分:
1.先从左上的表格开始,这部分展现了各省的累计数据和该省份各地区的数据,可点击展开或折叠,点击 3D 地图相应的位置筛选出该地区的相应数据单独展现,点击空白处恢复显示全国数据。
2.接下来是左下的疫情播报部分,这部分的数据采集了各地卫健委数据轮播展现,这里加上了表格纵偏移缓动效果使得滚动更天然美观。
3.底部最显眼的是最新的确诊,疑似,治愈,死亡等数据,往上的位置还有一条时间轴,点击旁边的播放按钮会动态改变页面的数据,根据不一样日期各地区确诊人数来对地图染色,与旁边的色卡对比能清晰地观察出各地区疫情的严重程度。
4.右侧图表展现了按时间排序的确诊,疑似,治愈,死亡等数据,一眼就能从图表中读出疫情的发展趋势。
5.上方导航栏,点击可预览 GIS 版的疫情地图, CDC 官网, 还有移动版的疫情地图。ide

3D 地图部分:函数

  1. 渐入效果。打开这个demo后 3D 地图 缓缓地从远处飞入眼前,过渡天然,这部分经过 ht 自带的 startAnim 函数实现,能够指定任意的缓动函数来实现不一样的飞入效果,这在接下来的篇幅里会介绍。
  2. 省份点击的效果,从武汉向外输出的流动动画,各省省会位置的旋转动画。

程序的示意图:

1)2D,3D 场景的执行和交互
动画

2)全局的事件管理器
整个项目中涉及到 2D, 3D 的交互比较多,于是用了一个全局事件管理器类实例来管理:ui

class NotifierManager {
    constructor() {
        this._eventMap ={};
    }

    add(key, func, scope, first = false) {
        let notify = this._eventMap[key];
        if (!notify) notify = this._eventMap[key] = new ht.Notifier();

        notify.add(func, scope, first);
    }

    fire(key, e) {
        const notify = this._eventMap[key];
        if (!notify) return;

        notify.fire(e);
    }
}

const event = new NotifierManager();

主要代码:

1)点击 3D 地图
使用 ht 的事件派发改变 2D 内容:
this

相关代码以下:设计

event.fire('clickProvince', {
    data : this.g3dProvince,
    node : data
});
clickProvince(dataList, node) { 
    let province = node.getDisplayName();
    // 选中的省份透明度为1,其余为0.4
    dataList.forEach(data => {
        data.s('shape3d.opacity', data === node ? 1: 0.4 );
    })
    // 只显示该省份数据
    if (this.areaDatas && this.areaDatas.length > 0) {
        let provinceData = [];
        this.areaDatas.forEach((item) => {
            if (item.area === province || item.host === province) {
                item.expand = true;
                provinceData.push(item);
            }
        });
        this.detailTable.a('ht.dataSource', provinceData);
    }
}

2)滑块播放
滑块播放使用了 startAnim 的 Frame-Based 来开启动画:

相关代码以下:

// 滑块播放
playDateSlider() {
    this.playMenu.s('state', '暂停');
    let value =  this.dateSlider.a('ht.value');
    let x = this.dateSlider.a('dateArea')[0];
    // 若是到了最后一天的数据重置
    if (value >= 100 || x >= SLIDER_TIP_END_X) {
        // 重置地图背景色
        event.fire('resetMapColor');
        value = this.sliderValue = 0;
        x = SLIDER_TIP_START_X;
        this.dateSlider.s({
            'ht.value' : 0,
            'text' : this.sliderDateList[0],
        });
        this.dateSlider.a('dateArea', [SLIDER_TIP_START_X, SLIDER_TIP_Y, SLIDER_TIP_WIDTH, SLIDER_TIP_HEIGHT]);
    }
    // 开启动画
    this.sliderAnim = ht.Default.startAnim({
        frames: 100,
        interval: 300,
        action: () => {
            this.onPlay = true;
            this.timerJudgment(value);
            // 到最大值时停留
            if (value === 100) {
                this.onPlay = false;
                this.dateSlider.a('ht.value', value);
                // 最新数据
                this.initBottom(17);
                this.playMenu.s('state', '播放');
                this.sliderAnim.stop();
            };
            value += 1;
            this.sliderValue += 1;
            this.dateSlider.a('ht.value', value);
            x += STRIDE;
            if (x >= SLIDER_TIP_END_X) {
                this.dateSlider.a('dateArea', [SLIDER_TIP_END_X, SLIDER_TIP_Y, SLIDER_TIP_WIDTH, SLIDER_TIP_HEIGHT]);
            }
        }
    })
}

3)3D 入场动画
对于视角变化类的动画,ht 自带了 moveCamera 方法。相关代码以下:

function flyToView(g3d, eye, center, cb) {
    g3d.moveCamera(eye, center, {
        duration: 3000,
        easing: Easing.swing,
        finishFunc: function () {
            if (cb) {
                cb();
            } else {
                return;
            }
        }
    });
}

4) 2D 表格动画。
每隔 1.5 秒改变表格的纵向偏移值,并把这个过程经过帧动画的方式播放出来,实现流畅的浏览体验,相关代码以下:

// 疫情播报动画
playTable() {
    let table =  this.newsTable;
    // 表格 Y 轴偏移
    let translateY =  table.a('ht.translateY');
    this.tableInterval = ht.Default.startAnim({
        frames: Infinity,
        interval: 1500,
        action: () => {
            if (translateY < 0) {
                translateY = 0;
            }

            let temp = this.articleDataSource.shift();
            this.articleDataSource.push(temp);
            
            ht.Default.startAnim({
                frames: 20,
                interval: 10,
                finishFunc: () => {
                    translateY -= 32;
                },
                action: (v, t) => {
                    table.a('ht.translateY', translateY - 32 * v); 
                }
            });
        }
    });
}

5) 预览其余版本的疫情地图和 CDC 官网
使用 ht 的事件派发进行图纸加载和切换处理,以 GIS 版的为例:

相关代码以下:

if (kind === 'mobile') {
    event.fire('showMobile');
} 
else if (kind === 'cdc') {
    event.fire('showCdc');
} 
else if (kind === 'gis') {
    event.fire('showGis');
}

总结

疫情地图 PC 版大体效果就是这些,能够感觉到到现代浏览器支持的 3D 技术可实现很是直观的效果,互动性也很好。物联网和即将到来的 5G 给众多行业带来了新的机遇,也带来了新的挑战,海量的数据该如何更生动地展现在人们面前?经过跨平台的浏览器无疑是最好的选择。WebGL 技术依托于浏览器,对于数据的处理有着自然的优点,图扑软件做为在工业可视化领域的一线重度参与者,沉淀了许许多多宝贵的行业经验,前不久对刚过去的 19 年作了总结回顾和分享,整理出了 《2019-分享数百个 HT 工业互联网 2D 3D 可视化应用案例分享》,但愿各位看官们喜欢。

写在最后

当前,在举国上下一盘棋,戮力同心战疫情的不懈奋斗下,疫情的传播与蔓延已经获得初步控制。当突发事件来临时我很幸运本身是这个国家的一员,面对疫情时各个公共机构的执行力有效地扼制了疫情的扩散,一方有难八方支援,保证了各地区物资供给,也越发坚决了全国人民打赢这场战役的决心。但遗憾的是,新冠病毒的魔爪却伸向了世界其余地方,但我相信在中国人民和世界各国人民的共同合做抗争下,必定能阻止这场灾难的蔓延。图扑科技也将关注最新的动态,以本身的方式为疫情加油助力。这里作个预告,世界版的疫情地图很快就会与你们见面,敬请期待!
原文连接:http://www.javashuo.com/article/p-nujndiai-gn.html

相关文章
相关标签/搜索