Ts+vue3疫情可视化项目

疫情可视化

申明:学习自B站up:小满zs(https://space.bilibili.com/99210573),仅记录一下学习笔记

数据分析

数据地址:实时更新:新冠肺炎疫情最新动态 (qq.com)

在控制台网络中查看Fetch/XHR里的list 即为疫情数据

Ts+vue3疫情可视化项目_第1张图片

初始化项目

服务器端

npm install ts-node -g
npm init -y
npm install @types/node -D  //node 申明文件
npm install express -S
npm install @types/express -D  //express 申明文件
npm install axios -S

Ts+vue3疫情可视化项目_第2张图片

Index.ts

import express,{Express,Router,Request,Response} from 'express'
import axios from 'axios'
const app:Express = express()
// 设置跨域允许
app.use('*',(req,res,next) => {
    res.header('Access-Control-Allow-Origin','*')
    next();
})

const router:Router = express.Router()
app.use('/api',router)

router.get('/list',async (req:Request, res:Response) => {
    const result = await axios.post('https://api.inews.qq.com/newsqa/v1/query/inner/publish/modules/list?modules=localCityNCOVDataList,diseaseh5Shelf')
    res.json({
        data:result.data
    })
})

app.listen(3333,()=>{
    console.log('server listening on 3333!')
})

疫情数据接口:http://localhost:3333/api/list(个人的)

添加运行脚本

Ts+vue3疫情可视化项目_第3张图片

前端

安装库

npm init vue@latest

Ts+vue3疫情可视化项目_第4张图片

npm install

要同时安装less和lessload,其实在vite中只需要安装less即可,另一个可以不用安装,vite官网有说明.sass同理

npm install less

1.基本样式:App.vue







2.安装axios 创建文件夹

npm install axios

Ts+vue3疫情可视化项目_第5张图片

import axios from 'axios'

const server = axios.create({
    baseURL: "http://localhost:3333",
})

export const getApiList = () => server.get('/api/list').then(res => res.data)

3.修改stores文件夹

Ts+vue3疫情可视化项目_第6张图片

import { defineStore } from 'pinia'
import {getApiList} from '../server'

export const useStore = defineStore({
  id:'counter',
  state:()=>({
    list:{},
  }),
  actions:{
    async getList(){
      const result = await getApiList()
      console.log(result)      
    }
  }
})

3.在app.vue调用

import {useStore} from "./stores"
const store = useStore();
store.getList()

绘制地图

前期准备

npm install echarts --save-dev

引入china.js包

Ts+vue3疫情可视化项目_第7张图片
包我放在了源代码里,可自行在最下面源代码里获取

新建geoMap.ts:

Ts+vue3疫情可视化项目_第8张图片

export const geoCoordMap: Record<string, Array<number>> = {
    '台湾': [121, 23],
    '黑龙江': [127, 48],
    '内蒙古': [110.3467, 41.4899],
    "吉林": [125.8154, 44.2584],
    '北京': [116.4551, 40.2539],
    "辽宁": [123.1238, 42.1216],
    "河北": [114.4995, 38.1006],
    "天津": [117.4219, 39.4189],
    "山西": [112.3352, 37.9413],
    "陕西": [109.1162, 34.2004],
    "甘肃": [103.5901, 36.3043],
    "宁夏": [106.3586, 38.1775],
    "青海": [99.4038, 36.8207],
    "新疆": [87.9236, 43.5883],
    "西藏": [88.388277, 31.56375],
    "四川": [103.9526, 30.7617],
    "重庆": [108.384366, 30.439702],
    "山东": [117.1582, 36.8701],
    "河南": [113.4668, 34.6234],
    "江苏": [118.8062, 31.9208],
    "安徽": [117.29, 32.0581],
    "湖北": [114.3896, 30.6628],
    "浙江": [119.5313, 29.8773],
    "福建": [119.4543, 25.9222],
    "江西": [116.0046, 28.6633],
    "湖南": [113.0823, 28.2568],
    "贵州": [106.6992, 26.7682],
    "云南": [102.9199, 25.4663],
    "广东": [113.12244, 23.009505],
    "广西": [108.479, 23.1152],
    "海南": [110.3893, 19.8516],
    '上海': [121.4648, 31.2891],
    '香港': [114.30, 22.9],
    '澳门': [113.5, 22.2]
  }; 

App.vue:绘制地图


解决stores 空对象全局变量的报错问题

使用vscode插件json2ts,将数据放入index.json后 ctrl + alt + v,即可根据数据自动生成接口

Ts+vue3疫情可视化项目_第9张图片

Ts+vue3疫情可视化项目_第10张图片

然后在stroes文件夹里引入,即可解决Typescript报错问题,因为如果定义空对象,会默认下面没有其他属性而报错。

Ts+vue3疫情可视化项目_第11张图片

绘制表格

1.修改store

添加childrenList数据,用于存储列表数据

Ts+vue3疫情可视化项目_第12张图片

2.点击事件

为图表添加监听事件,点击打印相关数据,这里点击将store的childrenLIst进行修改,后续用于列表的数据

  chart.on('click',(event:any)=>{
    // console.log(city)
    console.log(event)
    store.childrenList = event.data.source.children
    console.log(store.childrenList)
  }) 

3.绘制表格

html:

      <table id="customers">
        <tr>
          <th>名称th>
          <th>治愈th>
          <th>确诊th>
          <th>本土确诊th>
        tr>
        <tr v-for="(item,index) in store.childrenList" :key="index">
          <td>{{item.name}}td>
          <td>{{item.total.confirm}}td>
          <td>{{item.today.confirm}}td>
          <td>{{item.today.local_confirm_add}}td>
        tr>
      table>

css:

#customers {
  font-family: Arial, Helvetica, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

#customers td, #customers th {
  border: 1px solid #ddd;
  padding: 8px;
}

#customers tr:nth-child(even){background-color: #f2f2f2;}

#customers tr:hover {background-color: #ddd;}
#customers tr {background-color: #ddd;text-align: center}
#customers th {
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: #4CAF50;
  // color: rgb(255, 255, 255);
}

4.添加动画

安装animate.css: npm install animate.css -S

引入:import 'animate.css'

设置群体动画一定要设置key,且唯一,因为index重复后,有的动画不会展示,因此使用uuid解决唯一值

assets文件夹新建getUUID.ts:

export function getUuid () {
  if (typeof crypto === 'object') {
    if (typeof crypto.randomUUID === 'function') {
      return crypto.randomUUID();
    }
    if (typeof crypto.getRandomValues === 'function' && typeof Uint8Array === 'function') {
      const callback = (c) => {
        const num = Number(c);
        return (num ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (num / 4)))).toString(16);
      };
      return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, callback);
    }
  }
  let timestamp = new Date().getTime();
  let perforNow = (typeof performance !== 'undefined' && performance.now && performance.now() * 1000) || 0;
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    let random = Math.random() * 16;
    if (timestamp > 0) {
      random = (timestamp + random) % 16 | 0;
      timestamp = Math.floor(timestamp / 16);
    } else {
      random = (perforNow + random) % 16 | 0;
      perforNow = Math.floor(perforNow / 16);
    }
    return (c === 'x' ? random : (random & 0x3) | 0x8).toString(16);
  });
};

引入:import {getUuid} from "./assets/getUUID"

修改点击事件:

  chart.on('click',(event:any)=>{
    // console.log(city)
    // console.log(event)
    event.data.source.children.map((child:any)=>{
      child['index']= getUuid()
    })
    store.childrenList = event.data.source.children
    // console.log(store.childrenList)
  }) 

html:

        <transition-group enter-active-class="animate__animated animate__backInRight" tag="tbody">
          <tr v-for="(item) in store.childrenList" :key="item.index">
            <td>{{item.name}}td>
            <td>{{item.total.confirm}}td>
            <td>{{item.today.confirm}}td>
            <td>{{item.today.local_confirm_add}}td>
          tr>
        transition-group>

其他和源代码

其他图表实现原理一样,因此就不展示了,走了一遍流程。

源代码

你可能感兴趣的:(javascript,前端,vue.js,typescript)