主頁 > 企業開發 > 疫情可視化(后續)

疫情可視化(后續)

2022-11-07 07:59:35 企業開發

前言

這是疫情可視化最開始的文章,有需要了解的可前往查看:https://www.cnblogs.com/xi12/p/16690119.html, 本來說有時間就把這個專案完結了的,結果后面一直有事拖著,直到現在十一月份了才搞完,老樣子,先看成果,

  • 瀏覽鏈接:https://xi1213.gitee.io/covid19-visualization
  • 專案鏈接(歡迎各位大哥star):https://gitee.com/xi1213/covid19-visualization

修改與添加

后面可能審美疲勞了,越看越丑,就干脆直接用dataV(這可不是阿里的那個dataV)修飾頁面了,這是專案改動后的樣子:
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
主要做了如下改動:

  1. 添加首頁的3d粒子球體,
  2. 完成“省內分析”模塊,
  3. 完成當地疫情報告生成與下載,
  4. 使用dataV修飾頁面,

粒子球體

粒子球體也是用three.js完成的,放大仔細看會發現其實是有三層構成的:內層透明球體,中間點狀球體,外層病毒球體,
在這里插入圖片描述

具體實作程序是這樣的:

  1. 先繪制一個內層透明球體,記得將球體材質的transparent設為true,然后設定不透明度opacity值,
//創建斑點球體
async function createSpotSphere() {
  let globeBufferGeometry = new THREE.SphereGeometry(earthSize - 1, 50, 50);//球體幾何體
  let globeInnerMaterial = new THREE.MeshBasicMaterial({
    color: new THREE.Color(dvColor[0]),//顏色
    // blending: THREE.AdditiveBlending,//紋理融合的疊加方式
    // side: THREE.FrontSide,//前面顯示
    transparent: true,//透明
    // depthWrite: false,//深度寫入
    // depthTest: false,//黑洞效果
    opacity: .3,//不透明度
  });
  let globeInnerMesh = new THREE.Mesh(
    globeBufferGeometry,
    globeInnerMaterial
  );
  earthGroup.add(globeInnerMesh); //將網格放入地球組
  cre
  1. 創建點狀球體,這里需要使用一張黑白的世界地圖,
let img = new Image();
img.src = https://www.cnblogs.com/xi12/archive/2022/11/06/earthGrayscale; //黑白地圖

將圖片使用onload加載到專案中后,利用canvas繪制一遍該圖,再使用getImageData獲取到像素點資料canData,

let canvas = document.createElement("canvas");
    canvas.width = img.width; //使得canvas尺寸與圖片尺寸相同
    canvas.height = img.height;
    (canvas.getContext("2d") as any).drawImage(img, 0, 0, img.width, img.height);//canvas繪制圖片
    let canData = https://www.cnblogs.com/xi12/archive/2022/11/06/(canvas.getContext("2d") as any).getImageData(0, 0, canvas.width, canvas.height);//獲取畫布像素資料

利用canData .data中的rgba資訊生成緩沖幾何頂點陣列globeCloudVerticesArray,

let globeCloudBufferGeometry = new THREE.BufferGeometry(); //設定緩沖幾何體
    let globeCloudVerticesArray = []; //地球云緩沖幾何體頂點
    let o = null; //陣列處理時的計數
    for (o = 0; o < canData.data.length; o += 4) {
      let r = (o / 4) % canvas.width,
        i = (o / 4 - r) / canvas.width;
      if ((o / 4) % 2 == 1 && i % 2 == 1)
        if (0 === canData.data[o]) {
          let n = r,
            longitude = (i / (canvas.height / 180) - 90) / -1, //經度
            latitude = n / (canvas.width / 360) - 180; //維度
          let s = latLongToVector3(longitude, latitude, earthSize, .1); //經緯度變換
          globeCloudVerticesArray.push(s); //將變換后的頂點放入陣列
        }
    }

然后再使用three中的BufferAttribute生成屬性position與color,

let l = new Float32Array(3 * globeCloudVerticesArray.length); //創建頂點陣列長度
    for (o = 0; o < globeCloudVerticesArray.length; o++) {
      l[3 * o] = globeCloudVerticesArray[o].x;//設定頂點陣列資料
      l[3 * o + 1] = globeCloudVerticesArray[o].y;
      l[3 * o + 2] = globeCloudVerticesArray[o].z;
    }
    let positionVal = new THREE.BufferAttribute(l, 3); //設定緩沖區屬性值
    globeCloudBufferGeometry.setAttribute("position", positionVal); //給緩沖幾何體添加位置屬性
    let globeCloudMaterial = new THREE.PointsMaterial({
      color: new THREE.Color(dvColor[1]),//顏色
      fog: true,
      size: 1,
    });//球面斑點材質
    let d = new Float32Array(3 * globeCloudVerticesArray.length), c = [];
    for (o = 0; o < globeCloudVerticesArray.length; o++) {
      c[o] = new THREE.Color(dvColor[1]);//球面斑點顏色
      d[3 * o] = c[o].r;//設定地球云陣列rgb顏色
      d[3 * o + 1] = c[o].g;
      d[3 * o + 2] = c[o].b;
    }
    let color_val = new THREE.BufferAttribute(d, 3);
    globeCloudBufferGeometry.setAttribute("color", color_val);//給緩沖幾何體添加顏色屬性,修改顏色直接修改globeCloudBufferGeometry的setAttribute

最后再使用THREE.Points創建球面的點,將position與color屬性添加到點的幾何體BufferGeometry中,

let globeCloud = new THREE.Points(//球面的象素點
      globeCloudBufferGeometry,
      globeCloudMaterial
    );

這是需要用到的坐標轉換方法:

//經緯度坐標變換(傳入e:緯度、a經度、t球半徑、o球額外距離)
function latLongToVector3(e: any, a: any, t: any, o: any) {
  var r = (e * Math.PI) / 180,
    i = ((a - 180) * Math.PI) / 180,
    n = -(t + o) * Math.cos(r) * Math.cos(i),
    s = (t + o) * Math.sin(r),
    l = (t + o) * Math.cos(r) * Math.sin(i);
  return new THREE.Vector3(n, s, l); //計算三維向量
};
  1. 創建最外層的病毒球體,每一個病毒都是一個THREE.Sprite,材質是THREE.SpriteMaterial,利用Sprite.position.set設定具體坐標位置,最后將Sprite添加到球體組中,病毒的顏色是由當前點確診值決定的,顏色值在colors陣列中取出,
//創建病毒
function createVirus(data: any, earthSize: any) {
  let colors = [
    new THREE.Color(0xf9b8b8),
    new THREE.Color(0xfe4242),
    new THREE.Color(0xff0000),
  ]; //病毒顏色串列
  let virSize = 4; //病毒大小
  let list = JSON.parse(JSON.stringify(data));
  list.forEach((e: { value: number; color: any; position: any[]; }) => {
    e.value >= 10000000 && (e.color = colors[2]); //根據病毒數賦予不同顏色
    e.value >= 500000 && e.value < 10000000 && (e.color = colors[1]);
    e.value < 500000 && (e.color = colors[0]);
    if (e.position) {
      let virusMaterial = new THREE.SpriteMaterial({
        color: e.color,
        map: new THREE.TextureLoader().load(virusImg),
        side: THREE.FrontSide, //只顯示前面
      }); //病毒材質
      let Sprite = new THREE.Sprite(virusMaterial); //點精靈材質
      Sprite.scale.set(virSize, virSize, 1); //點大小
      let lat = e.position[1]; //緯度
      let lon = e.position[0]; //經度
      let s = latLongToVector3(lat, lon, earthSize, 1); //坐標轉換
      Sprite.position.set(s.x, s.y, s.z); //設定點的位置
      Sprite.dotData = https://www.cnblogs.com/xi12/archive/2022/11/06/e; //將點的資料添加到dotData屬性中
      Sprite.name ="病毒";
      earthGroup.add(Sprite); //將病毒添加進球體組中
    }
  });
};

省內分析

  1. 省內資料概況,
    在這里插入圖片描述
    該數值在加載時是有增加影片的,是利用vue回應式原理完成的,在上一篇文章中有提到,
  2. 省內各地疫情柱狀圖,
    在這里插入圖片描述
    這是具體的echart配置:
let option = {
        title: {
            text: provinceBaseData.value.province + "各地資料",
            left: "center",
            top: '5%',
            textStyle: {
                color: "#fff",
            },
        },
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'shadow'
            }
        },
        dataZoom: [
            {
                type: 'inside',
            },
            {
                show: true,
                yAxisIndex: 0,
                filterMode: 'empty',
                width: 25,
                height: '70%',
                showDataShadow: false,
                left: '3%',
                top: "center"
            }
        ],
        legend: {
            data: ['累計數', '治愈數', '確診數', '較昨日新增', '死亡數'],
            orient: "vertical",
            top: "15%",
            right: "2%",
            textStyle: {
                color: "#fff"
            },
        },
        grid: {
            left: '3%',
            right: '15%',
            bottom: '10%',
            containLabel: true
        },
        xAxis: {
            type: 'category',
            data: echartData.cityName,
            axisLabel: {
                interval: 0,
                rotate: 50,
                color: "#fff"
            },
        },
        yAxis: {
            type: 'value',
            axisLabel: {
                color: "#fff",
            },
        },
        series: [
            {
                name: '累計數',
                type: 'bar',
                emphasis: {
                    focus: 'series'
                },
                itemStyle: {
                    color: '#f59158'
                },
                data: echartData.conNum
            },
            {
                name: '治愈數',
                type: 'bar',
                emphasis: {
                    focus: 'series'
                },
                itemStyle: {
                    color: '#48c56b'
                },
                data: echartData.cureNum
            },
            {
                name: '確診數',
                type: 'bar',
                stack: 'total',
                emphasis: {
                    focus: 'series'
                },
                itemStyle: {
                    color: '#ffd889'
                },
                data: echartData.econNum
            },
            {
                name: '較昨日新增',
                type: 'bar',
                stack: 'total',
                emphasis: {
                    focus: 'series'
                },
                itemStyle: {
                    color: '#794ebd'
                },
                data: echartData.asymptomNum
            },
            {
                name: '死亡數',
                type: 'bar',
                stack: 'total',
                emphasis: {
                    focus: 'series'
                },
                itemStyle: {
                    color: '#ff6a6a'
                },
                data: echartData.deathNum
            },
        ]
    };
  1. 省份歷史疫情資料圖表,
    在這里插入圖片描述
    這是該圖表配置:
let option = {
        title: {
            text: provinceBaseData.value.province + "歷史資料",
            left: "center",
            top: '5%',
            textStyle: {
                color: "#fff",
            },
        },
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'cross',
                label: {
                    backgroundColor: '#6a7985'
                }
            }
        },
        legend: {
            data: ['累計數', '確診數', '較昨日新增', '治愈數', '死亡數'],
            orient: "vertical",
            top: "15%",
            right: "2%",
            textStyle: {
                color: "#fff"
            },
        },
        grid: {
            left: '8%',
        },
        xAxis: [
            {
                type: 'category',
                boundaryGap: false,
                axisLabel: {
                    color: "#fff",
                },
                data: echatrData.time
            }
        ],
        yAxis: [
            {
                type: 'value',
                axisLabel: {
                    color: "#fff",
                },
            }

        ],
        dataZoom: [
            {
                startValue: ''
            },
            {
                type: 'inside'
            }
        ],
        series: [
            {
                name: '累計數',
                type: 'line',
                stack: 'Total',
                smooth: true,
                lineStyle: {
                    width: 0
                },
                showSymbol: false,
                areaStyle: {
                    opacity: 0.8,
                    color: "#f59158"
                },
                emphasis: {
                    focus: 'series'
                },
                itemStyle: {
                    color: '#f59158'
                },
                data: echatrData.conNum
            },
            {
                name: '確診數',
                type: 'line',
                stack: 'Total',
                smooth: true,
                lineStyle: {
                    width: 0
                },
                showSymbol: false,
                areaStyle: {
                    opacity: 0.8,
                    color: "#ffd889"
                },
                itemStyle: {
                    color: '#ffd889'
                },
                emphasis: {
                    focus: 'series'
                },
                data: echatrData.econNum
            },
            {
                name: '較昨日新增',
                type: 'line',
                stack: 'Total',
                smooth: true,
                lineStyle: {
                    width: 0
                },
                showSymbol: false,
                label: {
                    show: true,
                    position: 'top'
                },
                areaStyle: {
                    opacity: 0.8,
                    color: "#794ebd"
                },
                itemStyle: {
                    color: '#794ebd'
                },
                emphasis: {
                    focus: 'series'
                },
                data: echatrData.asymptomNum
            },
            {
                name: '治愈數',
                type: 'line',
                stack: 'Total',
                smooth: true,
                lineStyle: {
                    width: 0
                },
                showSymbol: false,
                areaStyle: {
                    opacity: 0.8,
                    color: "#48c56b"
                },
                itemStyle: {
                    color: '#48c56b'
                },
                emphasis: {
                    focus: 'series'
                },
                data: echatrData.cureNum
            },
            {
                name: '死亡數',
                type: 'line',
                stack: 'Total',
                smooth: true,
                lineStyle: {
                    width: 0
                },
                showSymbol: false,
                areaStyle: {
                    opacity: 0.8,
                    color: "#ff6a6a"
                },
                itemStyle: {
                    color: '#ff6a6a'
                },
                emphasis: {
                    focus: 'series'
                },
                data: echatrData.deathNum
            },
        ]
    };

報告生成與下載

報告生成利用的是docxtemplater,這是前端生成word比較方便的一個插件,具體使用方法可以看這里:https://www.cnblogs.com/xi12/p/16863383.html,

  • 這是生成的word報告示例:
    在這里插入圖片描述

dataV修飾

  • dataV是一個大屏可視化組件庫,這是使用檔案:http://datav.jiaminghi.com/guide/,
  • dataV是vue2開始的,vue3使用的話會報錯,需要做一點修改,具體看這里:https://www.cnblogs.com/xi12/p/16859415.html,
  • 我只用了dataV中的一些邊框與裝飾,你在頁面中看到的紫色線框和一些影片的裝飾就是dataV的,還是蠻漂亮的,

結語

  • 最后我發現人的審美真的變化太快了,
  • 專案剛搞完:嗯不錯!真漂亮!
  • 過去一周后:什么玩意!丑得一批!
  • 如果還有后續的話,我可能就要考慮添加自定義主題配色了,

原創者:曦12

原文鏈接:https://www.cnblogs.com/xi12/p/16864419.html

轉載請注明原創者添加原文鏈接!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528096.html

標籤:其他

上一篇:js中的call,apply與bind

下一篇:第一百零五篇:變數的原始值和參考值

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more