0


vue3大屏可视化项目,包含地图,各种 图表,全屏适配方案

项目设计

请添加图片描述

1.始终满屏适配,这种方案一般用在屏幕变化不会特别的大项目,项目基本上不会用在比例非常不协调的大屏,设计图按1920*1080标准电脑屏幕比,所用的屏幕也基本在这个比例左右
2.涉及图表知识点简单,主要有自定义色系,环形图,堆叠柱状图,折线图
3.使用高德地图标点做中间地图

满屏适配方案实现思路

1 宽度使用vw,高度使用vh,严格按照设计图换算,并且留出缓冲空间
2 具体算法,设计图为1920*1080

高度上:
1.设计图上量取高度
2.高度除以设计图高度1080
3得到结果100
4计算结果加上vh单位3
宽度上:
设计图上量取宽度
高度除以设计图高度1920
得到结果
100
计算结果加上vw单位

3 特别提醒,因为我们大屏项目,高度要始终保持一屏,一般移动端项目高度不用一屏,是可以滚动的,所以高宽统一VW

项目头部制作

//<template><div class="headerContainer"><div class="header-title">大数据展示</div></div></template><script setup></script><style scoped>.headerContainer{width:100vw;height:6.85vh;

background-color: #030829;.header-title{color:white;

font-size:1.01vw;width:28.48vh;height:100%;

line-height:6.85vh;

text-align:center;margin:0 auto;

background-image:url("../assets/logoBg.png");

background-size:100%100%;}}</style>

项目请求和环境搭建

// request/index.jsimport axios from'axios'const request = axios.create({timeout:10000,baseURL:import.meta.env.VITE_BASE_URL})

request.interceptors.request.use((config)=>{return config

})

request.interceptors.response.use((res)=>{if(res.data.code !==200){alert("请求错误")}return res

},(res)=>{alert("请求错误")thrownewError(res)})exportdefault request
// api/index.jsimport request from'../request/index.js'exportfunctiongetGather(){return request.get("/getGather")}exportfunctiongetChargeData(){return request.get("/getCharGeData")}exportfunctiongetOutpatient(){return request.get("/getOutpatient")}exportfunctionhosiptalPostion(){return request.get("/hosiptalPostion")}exportfunctiongetHospitalization(){return request.get("/getHospitalization")}

在根目录创建.env.development和.env.production

VITE_BASE_URL="http://localhost:8000"

在App.vue

const loading =ref(true);asyncfunctiongetAllData(){//获取收费数据const chargeRes =awaitgetChargeData();//获取采集数const gatherRes =awaitgetGather()//获取门诊数据const hospitalizationRes =awaitgetHospitalization();//获取住院数据const outpatientRes =awaitgetOutpatient();//获取医院位置

loading.value =false;return{chargeRes: chargeRes.data.data,gatherRes: gatherRes.data.data,hospitalizationRes: hospitalizationRes.data.data,outpatientRes: outpatientRes.data.data

}}

顶部项目总览菜单

// components/showData.vue<script setup>const baseInfo =[{totalTitle:"总采集数据量",monthTitle:"当月采集量",totalIcon:"./info_1.png",monthIcon:"./info_2.png",color:"#ffff43"},{totalTitle:"总门诊数量",monthTitle:"当月门诊数量",totalIcon:"./info_3.png",monthIcon:"./info_4.png",color:"#25ebca"},{totalTitle:"总住院人数",monthTitle:"当月住院人数",totalIcon:"./info_5.png",monthIcon:"./info_6.png",color:"#ff4e4e"}]const props =defineProps(['data'])//第一次渲染->请求还没回来->页面渲染要先渲染出来</script><template><div class="showdataContainer"><div class="showdataBox" v-for="(item, index) in baseInfo"><div class="part"><div class="imgcontent"><img :src="item.totalIcon"/></div><div class="valuecontent"><div class="valuetitle">{{ item.totalTitle }}</div><div class="value":style="{color: item.color

}">{{ props.data[index]?.total }}</div></div></div><div class="part"><div class="imgcontent"><img :src="item.monthIcon"/></div><div class="valuecontent"><div class="valuetitle">{{ item.monthTitle }}</div><div class="value":style="{color: item.color

}">{{ props.data[index]?.month }}</div></div></div></div></div></template><style scoped lang="scss">.showdataContainer {display: flex;width:100%;

justify-content: space-between;.showdataBox {width:31.66vw;height:11.48vh;

background-color: #034c6a;display: flex;

align-items: center;

padding-left:1.3vw;

box-sizing: border-box;.part {width:50%;display: flex;.imgcontent {width:2.08vw;

margin-right:1.3vw;

  

img {width:100%}}.valuecontent {.valuetitle {

font-size:0.75vw;color: white;}.value {

margin-top:1.38vh;

font-size: 1vw;

font-weight:800;}}}}}</style>//App.vueasyncfunctiongetAllData(){//获取收费数据const chargeRes =awaitgetChargeData();//获取采集数const gatherRes =awaitgetGather()//获取门诊数据const hospitalizationRes =awaitgetHospitalization();//获取住院数据const outpatientRes =awaitgetOutpatient();//获取医院位置

  

loading.value =false;return{chargeRes: chargeRes.data.data,gatherRes: gatherRes.data.data,hospitalizationRes: hospitalizationRes.data.data,outpatientRes: outpatientRes.data.data

}}getAllData().then((res)=>{//进行数据赋值//形成上面数据概览所需要数据

dataofshowData.push({total: res.gatherRes.allgather,month: res.gatherRes.monthegather

},{total: res.hospitalizationRes.allHospitalization,month: res.hospitalizationRes.montHospitalization

},{total: res.outpatientRes.allOutpatient,month: res.outpatientRes.monthOutpatient

},)})<script><template><div class="container"><div v-if="!loading"><topHeader></topHeader><div class="mainbody"><showData :data="dataofshowData"></showData></div></div><div v-else>数据加载中请稍等</div></div></template>

主体布局设计

//App.vue<template><div class="container"><div v-if="!loading"><topHeader></topHeader><div class="mainbody"><showData :data="dataofshowData"></showData><div class="chartContainer"><div class="leftOrRight"><chartGather :data="chart1Data"></chartGather><chartCharge :data="chart2Data"></chartCharge></div><div class="middle"><chartMap></chartMap></div><div class="leftOrRight"><chartGatherToday :data="chart3Data"></chartGatherToday><chartHospitalizationToday :data="chart4Data"></chartHospitalizationToday></div></div></div></div><div v-else>数据加载中请稍等</div></div></template><style scoped lang="less">.container {width: 100vw;height: 100vh;

background-color: #081832;.mainbody {width: 100vw;

box-sizing: border-box;padding:1.85vh 1.04vw;.chartContainer {

padding-top:5.09vh;display: flex;

justify-content: space-between;.leftOrRight {display: flex;

flex-direction: column;

justify-content: space-between;}}}}</style><script>//引入四个组件import chartGather from"./components/chartGather.vue";import chartCharge from"./components/chartCharge.vue";import chartGatherToday from"./components/chartGatherToday.vue";import chartHospitalizationToday from"./components/chartHospitalizationToday.vue";</script>

chartContent.vue组件 布局组件

//component/chartContent.vue<script setup>const{ title }=defineProps(['title'])</script><template><div class="chartContentWrapper"><div class="chartContentTitle">{{ title }}</div><div class="chartContentMain"><slot></slot></div></div></template><style scoped lang="less">.chartContentWrapper {

box-shadow:-10px 0px 15px #034c6a inset,

0px -10px 15px #034c6a inset,

10px 0px 15px #034c6a inset,

0px 10px 15px #034c6a inset;position: relative;.chartContentTitle {width:14.15vw;height:3.7vh;

background-color: #034c6a;

border-radius: 50px;

text-align: center;color: white;position: absolute;left:50%;

margin-left:-7.075vw;top:-1.85vh;

line-height:3.7vh;

z-index:9999}}</style>

四个组件都布好局

//四个组件都是这样的布局  然后title字符串换换内容<template><div><chartContent title="各医院今日采集量"><div id="chart3Container":style="{width:'22.7vw',height:'33.19vh'}"></div></chartContent></div></template>
![[Pasted image 20240803193402.png]]

堆叠柱状图和圆环图

// component/chartGather.vue<script setup>import chartContent from'./chartContent.vue';import*as echarts from"echarts"import{ watch }from'vue';//引入echarts -》准备一个容器-》获取这个容器的真实dom-》init方法初始化图表-》setOptions给入配置绘制具体图表const props =defineProps(['data']);watch(props,()=>{if(props.data.length >0){const _dom = document.getElementById("gatherChartContainer")//以dom的大小为图表大小const echartobj = echarts.init(_dom);const opts ={color:['#87cefa','#ff7f50','#32cd32','#da70d6'],legend:{bottom:25,textStyle:{color:"#fff"}},series:[{type:"pie",radius:['40%','70%'],bottom:30,data: props.data,label:{show:false}}]}

echartobj.setOption(opts)}})</script><template><div><chartContent title="各医院采集数据量"><div id="gatherChartContainer":style="{width:'22.7vw',height:'33.19vh'}"></div></chartContent></div></template><style scoped lang="less"></style>//component/chartCharge.vue<script setup>import chartContent from'./chartContent.vue';import*as echarts from"echarts"import{ watch }from'vue';//引入echarts -》准备一个容器-》获取这个容器的真实dom-》init方法初始化图表-》setOptions给入配置绘制具体图表const props =defineProps(['data']);watch(props,()=>{if(props.data.length >0){const _dom = document.getElementById("chargeChartContainer")const echartobj = echarts.init(_dom);const opts ={grid:{left:"20%",bottom:"25%"},tooltip:{},legend:{bottom:35,textStyle:{color:"white"}},color:['#87cefa','#ff7f50','#32cd32','#da70d6'],yAxis:{type:"category",axisLabel:{color:"white"},data:['人均费用(元)','住院人次(人)','门诊人数(人)']},xAxis:{splitLine:{show:false},type:'value'},series:[]}

props.data.forEach((item)=>{

opts.series.push({type:"bar",stack:"total",name: item.name,data: item.data

})})

echartobj.setOption(opts)}})</script><template><div><chartContent title="各医院平均费用"><div id="chargeChartContainer":style="{width:'22.7vw',height:'33.19vh'}"></div></chartContent></div></template><style scoped lang="less"></style>

折线图与坐标轴自定义

// chartGatherToday.vue<script setup>import chartContent from'./chartContent.vue';import*as echarts from"echarts"import{ watch }from'vue';//引入echarts -》准备一个容器-》获取这个容器的真实dom-》init方法初始化图表-》setOptions给入配置绘制具体图表const props =defineProps(['data']);//data-[{name:'xxx',data:[1,2,3]}]watch(props,()=>{if(props.data.length >0){const _dom = document.getElementById("chart3Container")const echartobj = echarts.init(_dom);const opts ={grid:{bottom:'25%',left:'15%'},tooltip:{},legend:{bottom:35,textStyle:{color:"white"}},color:['#87cefa','#ff7f50','#32cd32','#da70d6'],yAxis:{axisLabel:{color:"white",formatter:(value)=>{return value +'k条'}},},xAxis:{axisLabel:{color:"white"},type:"category",data:["8:00","12:00","16:00","20:00"]},series:[]}

props.data.forEach((item)=>{

opts.series.push({type:"line",smooth:true,name: item.name,data: item.data

})})

console.log(opts);

echartobj.setOption(opts)}})</script><template><div><chartContent title="各医院今日采集量"><div id="chart3Container":style="{width:'22.7vw',height:'33.19vh'}"></div></chartContent></div></template><style scoped lang="less"></style>//chartHospitalizationToday.vue<script setup>import chartContent from'./chartContent.vue';import*as echarts from"echarts"import{ watch }from'vue';//引入echarts -》准备一个容器-》获取这个容器的真实dom-》init方法初始化图表-》setOptions给入配置绘制具体图表const props =defineProps(['data']);//data-[{name:'xxx',data:[1,2,3]}]watch(props,()=>{if(props.data.length >0){const _dom = document.getElementById("chart4Container")const echartobj = echarts.init(_dom);const opts ={grid:{bottom:'25%',left:'15%'},tooltip:{},legend:{bottom:35,textStyle:{color:"white"}},color:['#87cefa','#ff7f50','#32cd32','#da70d6'],yAxis:{axisLabel:{color:"white",formatter:(value)=>{return value +'人'}},},xAxis:{axisLabel:{color:"white"},type:"category",data:["8:00","12:00","16:00","20:00"]},series:[]}

props.data.forEach((item)=>{

opts.series.push({type:"line",smooth:true,name: item.name,data: item.data

})})

console.log(opts);

echartobj.setOption(opts)}})</script><template><div><chartContent title="就诊人数(今日)"><div id="chart4Container":style="{width:'22.7vw',height:'33.19vh'}"></div></chartContent></div></template><style scoped lang="less"></style>

地图开发和标记点

搜索高德开放平台。注册账号并打开网站

https://lbs.amap.com/api/javascript-api-v2/summary

根据里面文档看代码

//项目的根目录index.html文件
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><linkrel="icon"href="/favicon.ico"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Vite App</title></head><body><scripttype="text/javascript">

window._AMapSecurityConfig ={securityJsCode:"你的密钥",};</script><scriptsrc="https://webapi.amap.com/loader.js"></script><divid="app"></div><scripttype="module"src="/src/main.js"></script></body></html>
<script setup>//chartMap.vueimport chartContent from'./chartContent.vue';import{ hosiptalPostion }from'@/api';import{ onMounted }from'vue';import config from"@/global.config.js"functioncreateInfoWindow(AMap, mapObj, info){

console.log(info);let infoWindow =newAMap.InfoWindow({isCustom:true,content:`<div class="window-container">

${info.name}

</div>`})//第一个参数在哪个地图打开,第二参数打开的位置,info.postion

infoWindow.open(mapObj, info.position)}//标记点functioncreatPoint(AMap, mapObj, data){const marker =newAMap.Marker({position:newAMap.LngLat(data.position[0], data.position[1]),})

marker.on("click",(e)=>{createInfoWindow(AMap, mapObj,{name: data.hospitalName,position: e.target.getPosition()})})

mapObj.add(marker);}onMounted(()=>{hosiptalPostion().then((res)=>{const _data = res.data.data

//拿到数据进行绘制,AMapLoader,是引入高德地图后自动注入到window

AMapLoader.load({key: config.amapkey,//申请好的Web端开发者 Key,调用 load 时必填version:"2.0",//指定要加载的 JS API 的版本,缺省时默认为 1.4.15}).then((AMap)=>{const map =newAMap.Map("map1",{zoom:13,center: _data[0].position

})

_data.forEach((item)=>{creatPoint(AMap, map, item)})}).catch((e)=>{});});})</script><template><div><chartContent title="厦门市地图"><div id="map1":style="{width:'47.83vw',height:'72vh'}"></div></chartContent></div></template><style>.window-container {width: 100px;height: 50px;

text-align: center;

background-color: white;}</style>

最终实现效果

请添加图片描述

如果对你有所帮助的话 点个关注吧

这篇文章是这个视频的笔记

https://www.bilibili.com/video/BV1Hy411B79x/?spm_id_from=333.788&vd_source=e73709c9a1618b4c6dfd58c6c40d8986

本文转载自: https://blog.csdn.net/weixin_63625059/article/details/140901440
版权归原作者 ZhaiMou 所有, 如有侵权,请联系我们删除。

“vue3大屏可视化项目,包含地图,各种 图表,全屏适配方案”的评论:

还没有评论