700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > echarts dataV 数据可视化大屏

echarts dataV 数据可视化大屏

时间:2019-11-14 20:40:48

相关推荐

echarts dataV 数据可视化大屏

一、项目描述 (包含echarts中国地图、dataV科技炫酷边框等等)

一个基于 Vue、Datav、Echart 框架的 "数据大屏项目",通过 Vue 组件实现数据动态刷新渲染,内部图表可实现自由替换。部分图表使用 DataV 自带组件, 组件库基于Vue (React版) ,主要用于构建大屏(全屏)数据展示页面即数据可视化,具有多种类型组件可供使用。

项目环境:Vue-cli、DataV、Echarts、node

友情链接:

Vue 官 方文档Vue CLIDataV 官方文档echarts 实例,echarts API 文档

项目展示

二、主要文件介绍

三、项目注意点

引用的模块(先下载 install)

main.js

import Vue from 'vue'import App from './App.vue'import router from './router'import store from './store'import * as echarts from 'echarts' //echarts 引用使用断言,否则可能报错import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import dataV from '@jiaminghi/data-view'Vue.use(ElementUI); //部分图标使用 element-uiVue.use(dataV) //全局启用 dataVVue.prototype.$echarts=echarts //将echarts挂载到Vue原型上,全局可使用this.$echarts 调用Vue.config.productionTip = falsenew Vue({router,store,render: h => h(App)}).$mount('#app')

封装组件渲染图表

所有的 ECharts 图表已经对数据和屏幕改动进行了监听,能够动态渲染图表数据。在监听窗口小大的模块。

中间部分中国地图json数据来源 (地址)

我这边直接复制内容存到本地 (把复制的链接在网页打开Ctrl+A Ctrl+C 全选复制粘贴): assets > json > china.json

渲染地图的子组件

有几个注意点:

需要地图json文件需要监听数据变化tooltip: formatter 鼠标移入的提示信息框

<template><divid="map":style="{width: '700px',height: '730px',marginTop: '10px',}"></div></template><script>import china from "../assets/json/china.json"; //引入地图json文件export default {mounted() {this.initChart();},props: {mapData: {//接收父组件传过来的值type: Object,default: () => ({}),},},data() {return {options: {},chart: null,};methods: {// 地图initChart() {this.$echarts.registerMap("china", china); //echarts的map需要注册,根据引入的json文件名,并定义map的名称this.chart = this.$echarts.init(document.getElementById("map"), null, {renderer: "svg",}); //init()挂载在某个元素,所以还需要在mounted调用, { renderer: "svg" } 将原来的canvas绘图改为svg 清晰度更高this.drawMap();},drawMap() {this.chart.setOption({title: {text: "平台运营实时数据",textStyle: {color: "#fff",fontSize: 28,},},tooltip: {//鼠标移入的提示信息框show: true,trigger: "item",formatter: function (a, b) {// 将人数改千分位let a2 = "";let olda = Number(a["data"].value);if (olda >= 0) {a2 = olda;if (olda > 999) {let parts = olda.toString().split(".");parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");a2 = parts.join(".");}}// 日活兼容let a3 = a["data"].ratio ? a["data"].ratio : 0;let a1 = a["name"];if (a1 == "台湾省" && !a2) {// 台湾省显示暂无数据return `${a1}<br/> 暂无数据`;}return `${a1}<br/>累计注册: ${a2} <br/>日活: ${a3} %`;},},series: [{type: "map", map: "china", //对应registerMap() 对应的名称top: "150", //调整地图在页面的位置zoom: 1.3, //缩放比例emphasis: {label: {show: false },itemStyle: {areaColor: "rgba(136, 132, 216)",},},itemStyle: {borderColor: "#fff",},data: this.mapData.mapArr, //有数据才显示颜色},],visualMap: {show: true,type: "continuous",calculable: true,orient: "horizontal", textStyle: {color: "#fff",},min: 0,max: 10000000,text: ["累计注册/人", ""],color: ["#df3d20", "#fff"],inRange: {// color: [ "#fff","#44effb", "#3399ff","#2b8afe", "#006699"],color: ["#44effb", "#3399ff", "#2b8afe", "#006699"], //地图颜色},},},true);},},watch: {// handler 监听数据发生变化需要具体执行的方法// deep 需要监听的数据的深度,一般用来监听对象中某个属性的变化mapData: {handler() {this.drawMap();},deep: true, },},};</script><style></style>

复用图表组件(可以研究下)

更换边框 (炫酷的科技感动态边框)

边框是使用了 DataV 自带的组件,只需要去 views 目录下去寻找对应的位置去查找并替换就可以,具体的种类请去 DavaV 官网查看

如:

<dv-border-box-1> 内容撑开 </dv-border-box-1><dv-border-box-2> 内容撑开 </dv-border-box-2><dv-border-box-3> 内容撑开 </dv-border-box-3>

Mixins 解决自适应适配功能

使用 mixins 注入解决了界面大小变动图表自适应适配的功能,函数在utils/resizeMixins.js中,应用在common/echart/index.vue的封装渲染组件,主要是对this.chart进行了功能注入。

屏幕适配

使用更流程通用的css3:scale缩放方案,通过ref指向 主页面的元素,基准尺寸是1980px*1080px,所以支持同比例屏幕 100% 填充,如果非同比例则会自动计算比例居中填充,不足的部分则留白。实现代码在 `src/utils/drawMixin ,如果有其它的适配方案,欢迎交流。

src > utils > drawMixin.js

// 屏幕适配 mixin 函数//需要先设置index.html meta 标签 user-scalable=no//<meta name="viewport" content="width=device-width,initial-scale=1.0 ,user-scalable=no">//并且需要绑定ref // * 默认缩放值const scale = {width: '1',height: '1',}// * 设计稿尺寸(px)// 1920×1080const baseWidth =1920const baseHeight = 1080// * 需保持的比例(默认1.77778)const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))export default {data() {return {// * 定时函数drawTiming: null}},mounted () {this.calcRate()window.addEventListener('resize', this.resize)},beforeDestroy () {window.removeEventListener('resize', this.resize)},methods: {calcRate () {const appRef = this.$refs["appRef"]if (!appRef) return // 当前宽高比const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))if (appRef) {if (currentRate > baseProportion) {// 表示更宽scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)scale.height = (window.innerHeight / baseHeight).toFixed(5)appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`} else {// 表示更高scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)scale.width = (window.innerWidth / baseWidth).toFixed(5)appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`}}},resize () {clearTimeout(this.drawTiming)this.drawTiming = setTimeout(() => {this.calcRate()}, 200)}},}

homeword.vue

<template><div id="index" ref="appRef">...页面内容...</div></template><script>import drawMixin from "../utils/drawMixin";export default {components: {//.....},mixins: [drawMixin], //混入 (保持页面缩放比例)} </script>

请求数据

使用axios进行数据请求,在main.js位置进行全局配置。

src > request文件统一处理所有的请求

src > request > request.js请求和响应拦截

// 封装axios实例的拦截器(请求, 响应)import axios from 'axios';// 1. 创建axios实例const instance = axios.create({timeout: 15000, // 超时时间15sbaseURL: '这里是你请求是ip地址', // ip+端口, 公用的前缀路径});// 重写实例请求前拦截器instance.interceptors.request.use((config) => {return config;}, (err) => {return Promise.reject(err);})// 重写实例响应后拦截器instance.interceptors.response.use((result) => {return result.data;}, (err) => {return Promise.reject(err);})// 导出axios实例export default instance;

src > request > request.js请求拼接地址

import request from './request';// 主要指标 /mcpbd-data/data/mainIndexexport const getMainIndex= () => request.get('/mainIndex') //这里是get请求,"/mainIndex" 是接口文档的请求拼接字段//......

homeword.vue引入,并发送请求数据

由于一个页面要发送多个请求,并且成功获取数据再渲染,我使用了promise.all

并发请求,但是发现请求很慢(不知道有什么方法可以优化)

<template>...</template><script>import drawMixin from "../utils/drawMixin";//接口import {getMainIndex,} from "../request/httpApi";export default {components: {//...},mixins: [drawMixin],name: "HelloWorld",props: {},data() {return {//渲染子组件,还未请求到数据的时候,需要放数据的所有元素不显示falg: false,loading: true,loadTimer: null,resd: [],realVal: 0,MainIndicators: {// 主要指标 默认数据userAllCnt: "",userNewCnt: "",userDailyActvCnt: "",userDailyActvRatio: "",userMonthlyActvCnt: "",userMonthlyActvRatio: "",mctAllCnt: "",},//累计注册用户数折线//....mapData: {//地图数据mapArr: [],},};},mounted() {this.cancelLoading();},filters: {//过滤数据numFilter(val) {return (parseFloat(val) * 100).toFixed(1);},},created() {this.getJ();this.getShishi();// 实时更新数据(隔一个小时请求数据)setInterval(() => {this.getJ();}, 3600000);//左下角数据实时更新(1分钟)setInterval(() => {this.getShishi();}, 60000);},methods: {getShishi() {//左下角数据 (因为这部分数据需要每分钟更新一次所以单独拎出来)getRealTimeIndex() //发送请求.then((res) => {this.RealTimeIndex.newUserAllUserCnt = [];this.RealTimeIndex.newUserAllUserDate = [];this.resd = res;this.resd.forEach((item) => {this.RealTimeIndex.newUserAllUserCnt.push(Number(item.userAllCnt).toFixed()),this.RealTimeIndex.newUserAllUserDate.push(item.calTime.substring(11));});}).catch((err) => {return;});},sortData(attr) {return function (a, b) {return b[attr] - a[attr];};},getJ() {// 累计注册用户let p1 = new Promise((resolve, reject) => {getUserAllCnt().then((res) => {resolve(res);}).catch((err) => {reject(err);});});// 用户let p2 = new Promise((resolve, reject) => {//....});// 累计用户数let p3 = new Promise((resolve, reject) => {//....});// 日活用户数let p4 = new Promise((resolve, reject) => {//....});// 新增用户数let p5 = new Promise((resolve, reject) => {//....});// 指标排行表let p6 = new Promise((resolve, reject) => {//....});// 主要指标let p7 = new Promise((resolve, reject) => {getMainIndex().then((res) => {setTimeout(() => {resolve(res);}, 700);}).catch((err) => {reject(err);});});// 地图数据省份let p8 = new Promise((resolve, reject) => {//....});Promise.all([p1, p2, p3, p4, p5, p6, p7, p8]).then((res) => {// 累计注册用户//数据处理。。。// 日活//数据处理。。。// 累计用户数 (只展示前5条数据)//数据处理。。。// 日活用户数//数据处理。。。// 新增用户数//数据处理。。。// 指标排行表//数据处理。。。// 主要指标let mainIndex = res[6];this.MainIndicators.userAllCnt = Number(mainIndex.userAllCnt).toLocaleString("en-US"); //使用千分符this.MainIndicators.userNewCnt = Number(mainIndex.userNewCnt).toLocaleString("en-US");this.MainIndicators.userDailyActvCnt = Number(mainIndex.userDailyActvCnt).toLocaleString("en-US");this.MainIndicators.userDailyActvRatio = mainIndex.userDailyActvRatio;this.MainIndicators.userMonthlyActvCnt = Number(mainIndex.userMonthlyActvCnt).toLocaleString("en-US");this.MainIndicators.userMonthlyActvRatio =mainIndex.userMonthlyActvRatio;this.MainIndicators.mctAllCnt = Number(mainIndex.mctAllCnt).toLocaleString("en-US");// 地图省份指标let FenUserMap = res[7];this.mapData.mapArr = FenUserMap.map((item) => ({name: item.regionName,value: Number(item.userAllCnt).toFixed(),ratio: (Number(item.userActvDailyRatio) * 100).toFixed(1),}));//由于暂无数据隐藏南海诸岛,不太好,后面想到既然可以隐藏也可以将提示信息改成暂无数据this.mapData.mapArr.push({name: "南海诸岛",value: 0,itemStyle: {opacity: 0, label: {show: false } },});this.falg = true; //子组件渲染}).catch((err) => {});},cancelLoading() {if (!this.loadTimer) {this.loadTimer = setTimeout(() => {this.loading = false;}, 500);} else {clearTimeout(this.loadTimer);}},},destroyed() {},};</script>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。