基於 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

相關代碼以下:spa

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 可視化應用案例分享》,但願各位看官們喜歡。

寫在最後

當前,在舉國上下一盤棋,戮力同心戰疫情的不懈奮鬥下,疫情的傳播與蔓延已經獲得初步控制。當突發事件來臨時我很幸運本身是這個國家的一員,面對疫情時各個公共機構的執行力有效地扼制了疫情的擴散,一方有難八方支援,保證了各地區物資供給,也越發堅決了全國人民打贏這場戰役的決心。但遺憾的是,新冠病毒的魔爪卻伸向了世界其餘地方,但我相信在中國人民和世界各國人民的共同合做抗爭下,必定能阻止這場災難的蔓延。圖撲科技也將關注最新的動態,以本身的方式爲疫情加油助力。這裏作個預告,世界版的疫情地圖很快就會與你們見面,敬請期待!

相關文章
相關標籤/搜索