百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Vue+Echarts构建大数据可视化展示公司品牌项目分享(附源码)(下)

toyiye 2024-06-21 12:21 7 浏览 0 评论

回顾

前端的学习,不能仅仅依靠知识点的学习,实战项目的操作可以帮助我们整理知识点以及提高编程能力,更有助于学习和实践,最重要的是提高自己的项目经验,对于找工作而言有着大大的帮助。

作者用心之作,请动动你可爱的小手点亮大拇指。你的鼓励是作者继续创作的动力...

?

阅读本篇文章之前,可以先看看上一篇分享的内容,主要讲大数据可视化的由来,与前端的渊源,主题风格设计,选择比较流行的可视化第三方库。

一个基于Vue前端框架和第三方图表库Echarts构建的可视化大数据平台,通过vue项目构建、指令的灵活运用、组件封装、组件之间通信,使内部图表组件库可实现自由替换和组合。以及一些功能模块的设计及代码实现。

老规矩先上效果图(可视化酷屏展示公司品牌),后面会讲这个实例。

线上体验:jackchen0120.github.io/vueDataV/#/…

下面接着继续分享上一篇未讲完的内容。

自定义全局模态框

先看效果图:

自定义模态框已注册全局小组件在/components/modal目录文件,代码如下(含注解):

<template>
  <transition name="fade">
    <div class="modal-backdrop" v-if="visible">
      <div class="modal">
        <div class="modal-header">
          {{ title }}
          <i class="iconfont icon-close close" @click="close"></i>
        </div>
        <div class="modal-body">
            {{ content }}
        </div>
        <div class="modal-footer">
          <button type="button" class="btn-close" @click="close" v-if="showCancle">
            {{cancleText ? cancleText : '取消'}}
          </button>
          <button type="button" class="btn-confirm" @click="confirm">
            {{confirmText ? confirmText : '确定'}}
          </button>
        </div>
      </div>
    </div>
  </transition>
</template>
 
<script>

export default {
  name: 'Modal',
  props: {
    // modal标题
    title: {
      type: String,
      default: '提示'
    },
    // modal内容
    content: {
      type: String,
      default: ''
    },
    // 是否显示
    visible: {
      type: Boolean,
      default: false
    },
    // 是否显示取消按钮
    showCancle: {
      type: Boolean,
      default: true
    },
    // 确认按钮文字
    confirmText: {
      type: String,
      default: '确认'
    },
    // 取消按钮文字
    cancleText: {
      type: String,
      default: '取消'
    }
  },
  watch: {
    visible (curVal) {
      // 监听visible值的变化 
      console.log(curVal)
    }
  },
  methods: { 
    // 关闭按钮事件
    close() {
      this.$emit('update:visible', false);
    },
    // 确定按钮事件
    confirm() {
      this.close();
      this.$emit('confirm');
    }   
  }
}
</script>
复制代码

在components/index.js目录文件中注册全局组件,如下图:

完整代码如下:

// 引入自定义全局模态框组件
import modal from './modal' 

const components = {
  modal,
};

// install 是默认的方法。当外界在 Vue.use() 这个组件的时候,就会调用本身的 install 方法,同时传一个 Vue 这个类的参数。
const install = (Vue = {}) => {
  if (install.installed) return;
  Object.keys(components).forEach(component => {
    Vue.component(components[component].name, components[component]);
  });

  install.installed = true;
};

install.installed = false;

if (typeof window !== "undefined" && window.Vue) {
  install(window.Vue);
  install.installed = true;
}

// 定义组件库和install对象
const Vcomp = {
  ...components,
  install
};

// 导出
export default Vcomp
复制代码

在main.js中全局引用,如下图:

可在任意页面调用,代码如下:

<template>
 <div class="page">
   <modal 
       title="提示" 
       :content="modalContent"
       :visible.sync="visible" 
       @confirm="confirm">
      </modal>
 </div>
</template>

export default {
 data() {
  return {
   visible: true, // 显示模态框
        modalContent: '这是一段自定义模态框消息'
  }
 },
 methods: {
  confirm() {
   this.visible = false;
        console.log('点击确定')
  }
 }
}
复制代码

参数名 类型 说明 visible Boolean 是否显示,默认false title String 标题 content String 内容 confirmText String 确认按钮文字,默认“确认” cancleText String 取消按钮文字,默认“取消” showCancle Boolean 是否显示,默认true update:visible Boolean 更新visible, 使用:visible.sync实现动态绑定

数字滚动组件

推荐一款简单好用的数字滚动组件,vue-count-to是一个无依赖,轻量级的vue组件,可以自行覆盖easingFn。你可以设置 startVal 和 endVal,它会自动判断计数或倒计时。支持vue-ssr,vue-countTo参考于countUp.js。

  • npm安装依赖
npm install -D vue-count-to
复制代码
  • 示例代码:
<template>
  <countTo :startVal='startVal' :endVal='endVal' :duration='3000'></countTo>
</template>

<script>
  import countTo from 'vue-count-to';
  export default {
    components: { countTo },
    data () {
      return {
        startVal: 0,
        endVal: 2020
      }
    }
  }
</script>
复制代码
  • 选项:

属性 描述 数据类型 默认值 startVal 开始值 Number 0 endVal 结束值 Number 2020 duration 持续时间,以毫秒为单位 Number 3000 autoplay 自动播放 Boolean true decimals 要显示的小数位数 Number 0 decimal 十进制分割 String .(点) separator 分隔符 String ,(逗号) prefix 前缀 String ''(空字符串) suffix 后缀 String ''(空字符串) useEasing 使用缓和功能 Boolean true easingFn 缓和回调 Function —

*注意:当autoplay:true时,它将在startVal或endVal更改时自动启动

  • 功能:

函数名 描述 mountedCallback 挂载以后返回回调 start 开始计数 pause 暂停计数 reset 重置countTo

首页动态列表组件显示的数据,就引用了数字滚动特效,如下图:

代码如下图:

如需查看完整源代码请移步到作者的github仓库

讲讲炫酷展示公司品牌实例

功能模块
  • 天气和当前日期
  • 自定义词云图
  • 模拟飞机航线动效
  • 自动切换tab选项卡
  • 柱状图、饼图、折线图、南丁格玫瑰图
技术栈
基于 flexible.js + rem 智能大屏适配

之前首页大屏布局采用的是绝对定位,加上整体屏幕缩放进行适配(简单粗暴,不是很优雅)。 现在推荐一种智能大屏适配方式,选用flexible.js是淘宝移动端自适应解决方案,源码含注解如下:

// 首先是一个立即执行函数,执行时传入的参数是window和document
(function flexible(window, document) {
  // 返回文档的root元素
  var docEl = document.documentElement; 
  // 获取设备的dpr,即当前设置下物理像素与虚拟像素的比值
  var dpr = window.devicePixelRatio || 1; 

  // 设置默认字体大小,默认的字体大小继承自body
  function setBodyFontSize() {
    if (document.body) {
      // 调整body标签的fontSize,fontSize = (12 * dpr) + 'px'
      document.body.style.fontSize = 12 * dpr + 'px';
    } else {
      document.addEventListener('DOMContentLoaded', setBodyFontSize);
    }
  }
  setBodyFontSize();

  // set 1rem = viewWidth / 24
  function setRemUnit() {
    // 设置root元素的fontSize = 其clientWidth / 24 + 'px'
    var rem = docEl.clientWidth / 24;
    docEl.style.fontSize = rem + 'px';
  }
  setRemUnit();

  // 当页面展示或重新设置大小的时候,触发重新
  window.addEventListener('resize', setRemUnit);
  window.addEventListener('pageshow', function(e) {
    if (e.persisted) {
      setRemUnit();
    }
  });

  // 检测0.5px的支持,支持则root元素的class中有hairlines
  if (dpr >= 2) {
    var fakeBody = document.createElement('body');
    var testElement = document.createElement('div');
    testElement.style.border = '.5px solid transparent';
    fakeBody.appendChild(testElement);
    docEl.appendChild(fakeBody);
    if (testElement.offsetHeight === 1) {
      docEl.classList.add('hairlines');
    }
    docEl.removeChild(fakeBody);
  }
})(window, document);
复制代码

设计稿尺寸是1920px*1080px,所以将屏幕分成24等份。

sublime text 3 cssrem插件
// 先下载插件到本地
git clone https://github.com/flashlizi/cssrem
复制代码

进入packages目录:Sublime Text -> Preferences -> Browse Packages... 如下图:

将下载到本地的cssrem目录复制到packges目录里,如下图:

然后重启Sublime Text,参数配置如下图:

如果小伙伴使用的vscode编辑器,也可以安装此插件,打开扩展,搜索cssrem,点击安装,如下图:

配置设置,如下图:

改完后重启,插件效果如图:

Flex 布局

Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。可以简便、完整、响应式地实现各种页面布局。这里推荐阮一峰老师的Flex布局教程

动手之前,先来分析一下整个页面设计布局,整体布局分为上(头部模块)和下(主体模块),主体模块又分为左中右三部分。主体中间又分为上(数字滚动模块)和下(地图模块)。

头部布局样式采用的是定位position,主体模块column列容器,分三列,占比 3 : 5 : 3。主体代码如下:

<section class="mainbox">
  <div class="item left">
    flex: 3;
  </div>

  <div class="item center">
    flex: 5;
  </div>

  <div class="item right">
    flex: 3;
  </div>
</section>
复制代码
.mainbox {
  min-width: 1024px;
  max-width: 1920px;
  padding: 0.125rem 0.125rem 0;
  display: flex;
  .item {
    flex: 3;
    &.center {
      flex: 5;
      margin: 0 0.125rem 0.1rem;
      overflow: hidden;
    }
  }
}
复制代码

全屏设置背景图及头部布局样式,可以直接在/src/views/Brand.vue目录文件查看源代码。

补充说明头部有展示天气和当前时间,天气数据实时展示,通过axios的get方法调用第三方免费天气API接口,并且设置每小时获取一次最新数据。代码实现如下:

mounted() {
  this.getWeather();
  this.timer = setInterval(() => {
   this.getWeather();
  }, 1000 * 60 * 60)  
},
methods: {
  getWeather() { // 第三方天气api接口
    axios.get('https://www.tianqiapi.com/api/', {
      params: {
        appid: '26148275',
        appsecret: '2id6H48Y',
        version: 'v6'
      }
    }).then(res => {
      if (res.data) {
        if (res.data.wea_img == 'xue') {
          this.imgSrc = require('../assets/img/brand/xue.png');
        } else if (res.data.wea_img == 'yin') {
          this.imgSrc = require('../assets/img/brand/yin.png');
        } else if (res.data.wea_img == 'yu' || res.data.wea_img == 'bingbao') {
          this.imgSrc = require('../assets/img/brand/yu.png');
        } else if (res.data.wea_img == 'yun') {
          this.imgSrc = require('../assets/img/brand/yun.png');
        } else if (res.data.wea_img == 'wu') {
          this.imgSrc = require('../assets/img/brand/wu.png');
        } else if (res.data.wea_img == 'shachen') {
          this.imgSrc = require('../assets/img/brand/shachen.png');
        } else if (res.data.wea_img == 'lei') {
          this.imgSrc = require('../assets/img/brand/lei.png');
        } else {
          this.imgSrc = require('../assets/img/brand/qing.png');
        }
        this.weatcherData = res.data;
      }
    }).catch(err => {
      console.log(err)
    })
  }
}
复制代码

当前时间代码实现如下:

mounted() {
  this.nowTimes();
},
methods: {
  timeFormate(timeStamp) { //显示当前时间
    let newDate = new Date(timeStamp);
    let year = newDate.getFullYear();
    let month = newDate.getMonth() + 1 < 10 ? '0' + (newDate.getMonth() + 1) : newDate.getMonth() + 1;
    let date = newDate.getDate() < 10 ? '0' + newDate.getDate() : newDate.getDate();
    let hh = newDate.getHours() < 10 ? '0' + newDate.getHours() : newDate.getHours();
    let mm = newDate.getMinutes() < 10 ? '0' + newDate.getMinutes() : newDate.getMinutes();
    let ss = newDate.getSeconds() < 10 ? '0' + newDate.getSeconds() : newDate.getSeconds();
    let week = newDate.getDay();
    let weeks = ['日', '一', '二', '三', '四', '五', '六'];
    let getWeek = '星期' + weeks[week];
    this.week = getWeek;
    this.date = year + '.' + month + '.' + date;
    this.nowTime = hh + ':' + mm + ':' + ss;
  },
  nowTimes() {
    this.timeFormate(new Date());
    setInterval(this.nowTimes, 1000);
    this.clear();
  },
  clear() {
    clearInterval(this.nowTimes)
    this.nowTimes = null;
  },
}
复制代码
Echarts 图表和地图的基本使用

1)Echarts使用五部曲

1. 本项目采用cdn引入echarts.js文件(图表依赖这个js库)

index.html引入cdn

vue.config.js配置webpack

2. 准备一个具备大小的容器(生成的图表会放入这个容器内)

<div class="chart" id="chart" style="width: 480px; height: 240px;"></div>
复制代码

3. 初始化echarts实例对象(实例化echarts对象)

let myChart = echarts.init(document.getElementById('chart'));
复制代码

4. 指定配置项和数据 option(根据具体需求修改配置选项)

let option = {
  xAxis: {
    type: 'category',
    boundaryGap: false,
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [{
    data: [820, 932, 901, 934, 1290, 1330, 1320],
    type: 'line',
    areaStyle: {},
    smooth: true
  }]
};
复制代码

5. 将配置项设置给echarts实例对象(让echarts对象根据修改好的配置生效)

myChart.setOption(option);

// 让图表跟随屏幕自适应
window.addEventListener("resize", () => {
  myChart.resize();
});
复制代码

2)了解echarts基础配置

如需了解更多,请移步到Echarts官网查看相关文档。

3)制作柱状图图表

一般直接去echarts官网查找类似实例,适当分析,并且引入到页面中,再根据需求定制图表。官方实例地址:echarts.apache.org/examples/zh…

比如上图的效果是如何实现的呢?

作者悄悄地告诉你,其实有个很简单的方法,直接在Echarts社区查找,因为社区有很多活跃的Echarts使用者,经常贡献一些非常棒的图表示例。

本项目参考实例地址:gallery.echartsjs.com/editor.html…,经过修改调整,最终呈现的效果如上图。已封装注册全局小组件,源代码在/src/components/companySummary/business.vue目录文件,请自行查看。

4)Echarts map地图使用

也是参考社区例子:模拟飞机航线动效

实现步骤:

  • 首先下载引入中国地图china.js文件(文件存放路径:/src/assets/js/china.js)
  • 其次使用社区实例的配置即可,修改图例,标题,背景色,地图放大比例等达到你想要的效果。

这个例子是扩展案例,大家以后可以多看看社区里面的实例。

/* 约束屏幕尺寸 */
@media screen and (max-width: 1024px) {
  html {
    font-size: 42px !important;
  }
}
@media screen and (min-width: 1920) {
  html {
    font-size: 80px !important;
  }
}
复制代码

5)自定义词云图

先上效果图

上图效果,作者已封装注册全局小组件,源代码在/src/components/companySummary/wordCloud.vue目录文件,请自行查看。

首先下载echarts-wordcloud.min.js压缩文件(存放路径:/src/assets/js),并导入到wordCloud.vue模板文件中。代码如下:

<template>
  <div class="word-container"> 
    <div class="chart" id="chart_right1"></div>
  </div>
</template>

<script>
import '@/assets/js/echarts-wordcloud.min'

export default {
  name: "wordCloud",
  data() {
    return {
      timer: null
    }
  },
  mounted() {
    this.getEchartRight1();
    this.timer = setInterval(() => {
      this.getEchartRight1();
    }, 5000)
  },
  methods: {
    getEchartRight1() {
      let myChart = echarts.init(document.getElementById('chart_right1'));
      let option = {
        // tooltip: {
        //   show: false
        // },
        series: [{
          type: 'wordCloud',
          gridSize: 1,
          sizeRange: [12, 50],
          rotationRange: [-90, 90],
          rotationStep: 45,
          shape: 'diamond',
          width: '90%',
          textPadding: 0,
          autoSize: {
            enable: true,
            minSize: 6
          },
          textStyle: {
            normal: {
              textBorderColor: 'rgba(255,255,255,0.3)',
              textBorderWidth: 1,
              color: () => {
                return 'rgb(' + [
                  Math.round(Math.random() * 160),
                  Math.round(Math.random() * 160),
                  Math.round(Math.random() * 160)
                ].join(',') + ')';
              }
            },
            emphasis: {
              fontSize: 20,
              // shadowBlur: 10,
              // shadowColor: 'rgba(255,255,255, .1)'
            }
          },
          data: [{
            name: '区块链',
            value: 810
          }, {
            name: '云计算',
            value: 520
          },{
            name: "人工智能",
            value: 928
          },{
            name: "大数据",
            value: 906
          },{
            name: "工业互联网",
            value: 825
          },{
            name: "医疗",
            value: 514
          },{
            name: "质量溯源",
            value: 486
          },{
            name: "政务",
            value: 53
          },{
            name: "密码学",
            value: 927
          },{
            name: "金融行业",
            value: 1308
          },{
            name: "供应链",
            value: 693
          },{
            name: "公有链",
            value: 611
          },{
            name: "私有链",
            value: 512
          },{
            name: "联盟链",
            value: 382
          },{
            name: "数据共享",
            value: 312
          },{
            name: "文创版权",
            value: 187
          },{
            name: "天河链",
            value: 163
          },{
            name: "数据存证",
            value: 104
          },{
            name: "UDFS存储",
            value: 3
          },{
            name: "在线教育",
            value: 31
          },{
            name: "关联分析",
            value: 941
          },{
            name: "智慧停车",
            value: 585
          },{
            name: "链云生态",
            value: 473
          },{
            name: "应用层",
            value: 358
          },{
            name: "网络层",
            value: 246
          },{
            name: "数据层",
            value: 207
          },{
            name: "基础层",
            value: 194
          },{
            name: "智能合约",
            value: 104
          },{
            name: "去中心化",
            value: 87
          },{
            name: "数字货币",
            value: 415
          },{
            name: "酷屏",
            value: 253
          },{
            name: "可视化",
            value: 211
          },{
            name: "P2P",
            value: 116
          },{
            name: "数据挖掘",
            value: 1309
          }]
        }]
      }

      myChart.setOption(option, true);
      window.addEventListener('resize', () => {
        myChart.resize();
      });
    },
  },
  beforeDestroy() {
    clearInterval(this.timer);
  }
};
</script>
复制代码

参考配置说明:https://github.com/ecomfe/echarts-wordcloud


作者:懒人码农
链接:https://juejin.im/post/5efca542f265da22c058d8ed
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关推荐

CryptoChat:一款功能强大的纯Python消息加密安全传输工具

关于CryptoChatCryptoChat是一款功能强大的纯Python消息加密安全传输工具,该工具专为安全研究专家、渗透测试人员和红蓝队专家设计,该工具可以完全保证数据传输中的隐私安全。该工具建立...

为什么都说Python简单,但我觉得难?

Python普遍被大家认为是编程语言中比较简单的一种,但有一位电子信息的学生说自己已经学了C语言,但仍然觉得Python挺难的,感觉有很多疑问,像迭代器、装饰器什么的……所以他提出疑问:Python真...

蓝牙电话-关联FreeSwitch中继SIP账号通过Rest接口

蓝牙电话-关联FreeSwitch中继SIP账号通过Rest接口前言上一篇章《蓝牙电话-与FreeSwitch服务器和UA坐席的通话.docx》中,我们使用开源的B2B-UA当中经典的FreeSWIT...

技术分享|Sip与WebRTC互通-SRProxy开源库讲解

SRProxy介绍目前WebRTC协议跟SIP协议互通场景主要运用在企业呼叫中心、企业内部通信、电话会议(PSTN)、智能门禁等场景,要想让WebRTC与SIP互通,要解决两个层面的...

全网第N篇SIP协议之GB28181注册 JAVA版本

鉴于网上大部分关于SIP注册服务器编写都是C/C++/python,故开此贴,JAVA实现也贴出分享GB28181定义了了基于SIP架构的视频监控互联规范,而对于多数私有协议实现的监控系统...

「linux专栏」top命令用法详解,再也不怕看不懂top了

在linux系统中,我们经常使用到的一个命令就是top,它主要是用来显示系统运行中所有的进程和进程对应资源的使用等信息,所有的用户都可以使用top命令。top命令内容量丰富,可令使用者头疼的是无法全部...

Linux 中借助 perf 对 php 程序模拟CPU高的案例分析

导语本文是一篇Linux借助工具分析CPU高的优化案例,没有任何干货内容,很详细的展示了优化CPU高的具体步骤,非常适合初中级读者阅读!...

centos漏洞处理方法(centos podman)

centos服务器最近有诸多漏洞,修复命令及对应的漏洞整理后,分享给大家RHSA-2020:1176-低危:avahi安全更新yumupdateavahi-libsRHSA-2017:326...

Linux上的free命令详解(Buffer和Cache)

解释一下Linux上free命令的输出。下面是free的运行结果,一共有4行。为了方便说明,我加上了列号。这样可以把free的输出看成一个二维数组FO(FreeOutput)。例如:FO[2][1]...

linux 命令行之你真的会用吗?--free 基本用法篇

free命令行统计内存使用率及swap交换分区的使用率数据。是由sourceforge负责维护的,在ubuntu上其包名为procps,这个源码包中,除了free还有ps,top,vmstat,ki...

kong api gateway 初体验(konga github)

kongapigateway初体验(firstsight?)。Kong是一个可扩展的开源API层(也称为API网关或API中间件)。Kong运行在任何RESTfulAPI的前面,并通过插件...

在Ubuntu下开启IP转发的方法(ubuntu20 ip)

IP地址分为公有ip地址和私有ip地址,PublicAddress是由INIC(internetnetworkinformationcenter)负责的,这些IP地址分配给了注册并向INIC提...

基于 Kubernetes 的 Serverless PaaS 稳定性建设万字总结

作者:许成铭(竞霄)数字经济的今天,云计算俨然已经作为基础设施融入到人们的日常生活中,稳定性作为云产品的基本要求,研发人员的技术底线,其不仅仅是文档里承诺的几个九的SLA数字,更是与客户切身利益乃...

跟老韩学Ubuntu Linux系列-sysctl 帮助文档

sysctl一般用于基于内核级别的系统调优,man帮助手册如下。...

如何在 Linux/Unix/Windows 中发现隐藏的进程和端口

unhide是一个小巧的网络取证工具,能够发现那些借助rootkit、LKM及其它技术隐藏的进程和TCP/UDP端口。这个工具在Linux、UNIX类、MS-Windows等操作系统下都...

取消回复欢迎 发表评论:

请填写验证码