Advertisement

基于VUE + Echarts 实现可视化数据大屏展示效果

阅读量:

该项目为寿光市国际蔬菜科技博览会智慧农业系统——LED拼接屏展示,主要功能包括拼接屏的尺寸为1920px*1080px,支持实时时间、天气预报、蔬菜信息展示、图表数据统计等功能。前端采用Vue框架,后端使用Node.js和EzuiKit.js进行开发,支持视频播放、图表展示、展区监控、产品展示轮播及植物模型动画等功能。系统通过AXIE ML框架实现数据对接,支持Rtmp流媒体展示,具备良好的交互性和展示效果。

第XX届中国(寿光)国际蔬菜科技博览会智慧农业系统 — 基于LED拼接屏的智慧农业系统前端开发文档

上线后呈现效果:

一、开发需求及方案制定

确定现场led拼接屏的显示比例设置,基于1920×1080分辨率,全屏显示时屏幕完全填充,无滚动条干扰;

在产品设计阶段,我需要明确与产品设计相关的功能模块。

  • 第一屏相关功能:实时时间、当地天气、菜博会基本信息、图表数据统计(近三日人流量、寿光最近价格行情、菜博会新品种/新技术/新模式)、展区监控、产品图展示、中间菜博会宣传视频+场馆分布介绍图切换展示、下一页;
  • 第二屏相关功能:实时时间、当地天气、大棚基本信息、彩椒种植模型、传感器数据展示、大棚监控、设备数据展示、报警记录和农事记录数据展示、中间大棚植物生长三维动画、返回;
  • 第一屏与第二屏无缝切换且循环;

3、确认拼接屏展示时远程投屏的浏览器设置,根据页面所需实现的功能特性,选择兼容性最优的浏览器版本,最终确定采用360极速浏览器的兼容模式,兼容版本为IE10。

4、页面模块划分,确定两屏切换方案,编写公共样式;

二、功能实现(不局限于此):

  • 编码工具:Visual Studio Code
  • js框架:vue
  • 接口对接:axios

在两屏循环切换场景中,采用单页结构,并通过v-show组件来控制显示和隐藏的模块。由于在第一屏数据加载完成之后,我们即可提前获取到第二屏的接口数据并进行渲染,从而为用户提供更流畅的视觉体验。关于v-if与v-show的区别,建议参考官方文档:https://cn.vuejs.org/v2/guide/conditional.html]

  • 第一屏切换至第二屏:通过监听视频播放并显示图片,当视频播放结束后,会展示图片,停留30秒后切换到第二屏。特别地,当用户点击下一页按钮切换至第二屏时,第一屏的视频会自动停止播放。
    • 第二屏切换至第一屏:通过监听视频播放,同样的逻辑适用于第二屏切换回第一屏的处理。当用户点击上一页按钮切换至第一屏时,第二屏的视频会自动停止播放。

自适应功能:拼接屏无需额外配置或调整,直接连接即可使用;如果需要自适应功能,建议使用rem来实现。

Echarts(百度开发)提供了多种图表类型,包括曲线图、柱状图、雷达图和散点图。请先获取数据,然后再进行图表绘制。更多信息,请访问echarts官方文档:https://echarts.baidu.com/option.html#title

为当前项目配置安装echarts依赖项,使用npm install echarts -save完成。可以选择全局引入或按需引入策略,以满足不同的开发需求。其中,全局引入通常配置在main.js文件中。

import echarts from 'echarts'

Vue.prototype.$echarts = echarts

  • 按需:page1.vue

var echarts = require('echarts');

  • 页面使用;

例:寿光最新价格行情曲线图

复制代码
 <template>

    
     <div id="price-quotation" style="width: 6rem; height: 4rem"></div>
    
 <template>
    
  
    
 <script>
    
     var echarts = require('echarts');
    
     export default {
    
     data(){
    
         return{
    
             highPriceList: [], //寿光今日价格数据列表 - 高
    
             lowerPriceList: [], //寿光今日价格数据列表 - 低 
    
         }
    
     },
    
     created(){
    
         var that = this;
    
         // 先获取接口的价格数据
    
         that.getPrice();
    
         window.setInterval(() => {  //每小时请求一次接口
    
               setTimeout(that.getPrice, 0)
    
         }, 360000)
    
     },
    
     mounted(){
    
         //绘制曲线图
    
         that.drawDataTable1();
    
     },
    
     methods:{
    
         drawDataTable1(){
    
             // 基于准备好的dom,初始化echarts实例
    
             let myChart1 = echarts.init(document.getElementById('price-quotation'))
    
             console.log('图表中获取价格列表====')
    
             console.log(this.highPriceList)
    
             // 绘制图表
    
             myChart1.setOption({
    
               title: { text: '' },
    
               grid: { 
    
                   left: '10%', 
    
                   right: '8%', 
    
                   top:'20%',
    
               },  
    
               legend: {
    
                   top: '3%',
    
                   textStyle: {color: '#fff'},
    
                   itemGap: 20,
    
                   itemHeight: 10,
    
                   data:[
    
                     {name: '最高价'}, 
    
                     {name: '最低价'}
    
                   ]
    
               },
    
               color:['#28F2A8','#28D8FF'],
    
               xAxis: [
    
                   {
    
                       type: 'category',
    
                       data: ['大红柿子(精品)','贝贝小柿子','大龙茄子','红彩椒','黄彩椒'],
    
                       boundaryGap: false,
    
                       axisLabel: {
    
                           interval: 0,
    
                           textStyle: {
    
                               color: '#fff'
    
                           },
    
                       lineHeight: 24
    
                   },
    
                   axisLine: { // 坐标轴线
    
                   lineStyle: {
    
                       color: 'rgba(85,85,85,0.4)'
    
                   },
    
               },
    
               axisTick: {  //刻度线
    
                   show: false,
    
                   lineStyle: {
    
                       color: 'rgba(85,85,85,0.4)'
    
                   }
    
               }, 
    
               axisPointer: {
    
                   type: 'shadow'
    
               },                
    
           }
    
       ],
    
       yAxis: [
    
           {
    
               type: 'value',
    
               name: '元(斤)',
    
               min: 0,
    
               max: 10,
    
               interval: 2.5,
    
               nameTextStyle: {
    
                   color: '#fff',
    
               },
    
               axisLabel: {
    
                   formatter: '{value}',
    
                   textStyle: {
    
                       color: '#fff'
    
                   },
    
               },
    
               axisLine: {
    
                   lineStyle: {
    
                       color: 'rgba(85,85,85,0.4)'
    
                   }
    
               },
    
               axisTick: {
    
                   show: false,
    
                   lineStyle: {
    
                       color: 'rgba(85,85,85,0.4)'
    
                   }
    
               },
    
               splitLine:{ //去除网格线
    
                   show: true,
    
                   lineStyle: {
    
                       color: ['rgba(85,85,85,0.4)']
    
                   }
    
               },   
    
           },
    
           {
    
               type: 'value',
    
               axisLine: {
    
                   lineStyle: {
    
                       color: 'rgba(85,85,85,0.4)'
    
                   }
    
               }, 
    
           },
    
       ],
    
       series: [
    
           {
    
               name: '最高价',
    
               type : 'line',
    
               label : {
    
                 show: true,
    
                 position: 'top',
    
                 color: '#fff',
    
               },
    
               itemStyle: {
    
                   normal: {
    
                       lineStyle: {
    
                           width:2, //调整 线条的宽度 
    
                           color : '#28F2A8' //线条颜色 - 绿色
    
                       }
    
                   }
    
               },
    
               // showSymbol: false,
    
               smooth: true,
    
               barWidth : '20%',
    
               data: this.highPriceList,
    
           },  
    
           {
    
               name: '最低价',
    
               type : 'line',
    
               label : {
    
                 show: true,
    
                 position: 'bottom',
    
                 color: '#fff',
    
               },
    
               itemStyle: {
    
                   normal: {
    
                       lineStyle: {
    
                           width:2, //调整 线条的宽度 
    
                           color : '#28D8FF' //线条颜色 - 蓝色
    
                       }
    
                   }
    
               },
    
               // showSymbol: false,
    
               smooth: true,
    
               barWidth : '20%',
    
               data: this.lowerPriceList,
    
           },    
    
       ]
    
     });
    
       }
    
     }
    
 }
    
 </script>

展区监控,菜hibit官方使用的海康摄像头和录像机,该监控系统仅限于内网访问。我们采用了最为直接的方式,在展示电脑上嵌入海康DEMO视频片段,并通过样式调整实现了监控画面的实时显示。通过Vue框架内嵌iframe的方式,实现了监控画面的实时更新,并通过样式调整优化了显示效果。

复制代码
 <div id="page1-rvm1">

    
     <iframe src="http://127.0.0.1/en/cbhs2.html" frameborder="0" wmode="opaque" scrolling="no"></iframe>
    
 </div>

注意:

  • 海康的demoWeb 控件 V3.0 基于 ActiveX 和 NPAPI 开发,接口封装于 javascript 脚本,以 javascript 接口形式提供用户 集成,支持网页上实现预览、回放、云台控制等功能。该控件开发包仅支持 B/S 网页开发,不适用于 C/S 开发。
  • 安装activex控件,此处坑较多,我的电脑是windows10的系统,IE浏览器始终安装不成功,后再另一台windows7系统的IE10上成功安装了此控件,附上安装失败时的处理方式:https://www.nhxz.com/fanyi/18102974563ba21a90da13da.html

5、产品图展示,图片自动循环轮播,

  • npm install vue-awesome-swiper --save
复制代码
        1. /*全局引入*/

    
        2. import VueAwesomeSwiper from 'vue-awesome-swiper' 
    
        3. import 'swiper/dist/css/swiper.css' //这里注意具体看使用的版本是否需要引入样式,以及具体位置
    
        4. Vue.use(VueAwesomeSwiper)
  • 页面中使用
复制代码
        1. <swiper :options="swiperOption" ref="mySwiper">

    
        2.    <!-- slides -->             
    
        3.    <swiper-slide v-for="(item,index) in proImgList" :key="index">
    
        4.        <img class="img-cover" :src="item">
    
        5.    </swiper-slide>
    
        6. </swiper>

data中:

复制代码
 swiperOption: {  //绿色果蔬的产品轮播  
    
     direction: "horizontal",
    
     observer:true,//修改swiper自己或子元素时,自动初始化swiper 
    
     observeParents:true,//修改swiper的父元素时,自动初始化swiper 
    
     autoplay: {
    
       delay: 1500,          
    
       stopOnLastSlide: false,          
    
       disableOnInteraction: false,          
    
     }, 
    
     loop: true,    
    
     loopedSlides: 0,      
    
     initialSlide: 0,
    
     slidesPerView: 2,
    
     spaceBetween: '3.33%',        
    
     speed: 800, 
    
 },

监听:

复制代码
 computed: {

    
     swiper () {
    
       return this.$refs.mySwiper.swiper;
    
     }
    
 },

该植物种植模型在第二屏界面加载时,自动调用该函数进行处理。在不同阶段,会自动切换显示内容,时间间隔由系统自动控制。图片的显示效果通过CSS3的动画效果实现,淡入淡出效果自然流畅。

  • 页面使用:
复制代码
        1. <div class="growing">

    
        2.    <div class="g-item" v-for="(item,index) in growingList" :key="index" :class="{active: currentIndex==index}">
    
        3.      <div class="left-title">
    
        4.           <div class="title-line"></div>
    
        5.           <div class="flex">
    
        6.                <p class="step color-fff">{{item.id}}</p>
    
        7.                <div class="color-fff text">
    
        8.                    <h3>{{item.period}}</h3>
    
        9.                    <!-- <p>{{item.dataInfo}}</p> -->
    
        10.                 </div>
    
        11.            </div>
    
        12.       </div>
    
        13.       <img :src="item.imgSrc" alt="">
    
        14.     </div>
    
        15. </div>
  • js数组及函数

data中:

复制代码
 growingList: [  //种植模型

    
   {id: '01', period: '缓苗期管理', dataInfo: '(定植后1周)', imgSrc: 'static/images/growing1.png'},
    
   {id: '02', period: '定植期管理', dataInfo: '(定植后2~4周)', imgSrc: 'static/images/growing2.png'},
    
   {id: '03', period: '开花坐果期管理', dataInfo: '(定植后5~8周)', imgSrc: 'static/images/growing3.png'},
    
   {id: '04', period: '果实膨大期和成熟期管理', dataInfo: '(定植后9~11周)', imgSrc: 'static/images/growing4.png'},
    
   {id: '05', period: '采收期管理', dataInfo: '(雌花开放后37~40天采收第一批瓜)', imgSrc: 'static/images/growing4.png'},
    
 ],

监听:

复制代码
 watch: {

    
     currentPage (newValue, oldValue) {
    
       console.log("currentPage: "+newValue, oldValue);
    
       if(newValue == 2){
    
     // 种植模型
    
     this.plantModelAnt()
    
     this.pageSwitch2()
    
       }else{
    
     // console.log(newValue, oldValue)
    
     this.pageSwitch1()
    
       }
    
     },
    
 },

函数:

复制代码
 // 种植模型动画

    
 plantModelAnt(){
    
   var that = this;
    
   setTimeout(() => {
    
     console.log("当前展示屏===" +that.currentPage)
    
     if(that.currentIndex < 4){
    
     that.currentIndex += 1
    
     }else{
    
     that.currentIndex = 0
    
     }
    
     console.log('currentIndex====' + that.currentIndex)
    
     that.plantModelAnt()
    
   },11000)    
    
   
    
 },

7、大棚监控,使用的萤石云,在萤石的后台拿到对应的Rtmp流地址

  • 页面使用:
复制代码
        1. <video id="myPlayer" playsInline webkit-playsinline autoplay>

    
        2.      <source src="对应流地址" type="rtmp/flv" />
    
        3. </video>
  • 将EZuikit.js下载本地引入,修改下
复制代码
    import { EZuikit } from '../common/js/EZuikit.js'
复制代码
 mounted(){

    
     var player = new EZUIKit.EZUIPlayer('myPlayer');
    
 }

如有不懂请咨询QQ:1294487763,非相关请勿扰,谢谢!

打个广告

我承接微信公众号/小程序/可视化大屏/企业官网/管理系统等项目开发,有需要随时QQ联系我~ (¬_¬)

全部评论 (0)

还没有任何评论哟~