vue + echarts实现数据可视化统计页面

1、该项目自行下载element-ui、moment、echarts等vue的相关依赖包;

2、该项目里面的echarts样式主题“walden.js”是个人自己配置的样式,可到官网自行配置或者选择默认样式;


先上效果图:

标数据可视化网页

 


代码参考:

三个echarts子组件(比较懒,子组件代码就做出一个组件画一张图,可以通过JavaScript对dom元素进行操作实现一组件画多图的效果,以后会考虑写一下)

chart1.vue

<template>
  <div>
    <div id="myChart1" :style="{width: width + 'px', height: height + 'px'}"></div>
  </div>
</template>

<script>
import 'echarts/theme/walden.js'

export default {
  name: 'echart1',
  props: {
    digitalData: {
      type: Array,
      default () {
        return []
      }
    },
    xAxisText: {
      type: Array,
      default () {
        return []
      }
    },
    title: {
      type: String,
      default () {
        return ''
      }
    },
    width: {
      type: Number,
      default: 0
    },
    height: {
      type: Number,
      default: 0
    },
    xFontColor: {
      type: String,
      default: '#a7a7a7'
    }
  },
  data () {
    return {
    }
  },
  mounted () {
    this.drawChart()
  },
  methods: {
    drawChart () {
      // 这个地方已经写死了一个组件画一个图表,可以自行用代码获取dom节点的多图创建,
      // 而且这里的 'walden'也是我自己的echarts样式,可以用默认的,用默认就直接写成
      // var myChart = this.$echarts.init(document.getElementById('myChart1'))
      var myChart = this.$echarts.init(document.getElementById('myChart1'), 'walden')
      let option = {
        title: {
          text: this.title
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow'
          }
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '3%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          data: this.xAxisText,
          axisLabel: {
            show: true,
            textStyle: {
              color: this.xFontColor // 这里用参数代替了
            }
          }
        },
        yAxis: {
          type: 'value',
          axisLabel: {
            show: true,
            textStyle: {
              color: this.xFontColor // 这里用参数代替了
            }
          }
        },
        series: [{
          barWidth: '60%',
          data: this.digitalData,
          type: 'bar'
        }]
      }

      myChart.setOption(option, true)
    }
  }
}
</script>

<style scoped>
</style>

chart2.vue

<template>
  <div>
    <div id="myChart2" :style="{width: width + 'px', height: height + 'px'}"></div>
  </div>
</template>

<script>
import 'echarts/theme/walden.js'

export default {
  name: 'echart2',
  props: {
    leftText: {
      type: Array,
      default () {
        return []
      }
    },
    digitalData: {
      type: Array,
      default () {
        return []
      }
    },
    title: {
      type: String,
      default () {
        return ''
      }
    },
    width: {
      type: Number,
      default: 0
    },
    height: {
      type: Number,
      default: 0
    }
  },
  data () {
    return {
    }
  },
  mounted () {
    this.drawChart()
  },
  methods: {
    drawChart () {
      var myChart = this.$echarts.init(document.getElementById('myChart2'), 'walden')
      let option = {
        title: {
          text: this.title,
          left: 'center'
        },
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b} : {c} ({d}%)'
        },
        legend: {
          orient: 'vertical',
          left: 'left',
          data: this.leftText
        },
        series: [
          {
            name: '占比',
            type: 'pie',
            radius: '60%',
            center: ['60%', '50%'],
            data: this.digitalData,
            emphasis: {
              itemStyle: {
                shadowBlur: 10,
                shadowOffsetX: 0,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
              }
            }
          }
        ]
      }

      myChart.setOption(option, true)
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

chart3.vue

<template>
  <div>
    <div id='myChart3' :style="{width: width + 'px', height: height + 'px'}"></div>
  </div>
</template>

<script>
import 'echarts/theme/walden.js'

export default {
  name: 'echart3',
  props: {
    text: {
      type: Array,
      default () {
        return []
      }
    },
    digitalData: {
      type: Array,
      default () {
        return []
      }
    },
    title: {
      type: String,
      default () {
        return ''
      }
    },
    width: {
      type: Number,
      default: 0
    },
    height: {
      type: Number,
      default: 0
    },
    radius: {
      type: Number,
      default: 100
    }
  },
  data () {
    return {}
  },
  mounted () {
    this.drawChart()
  },
  methods: {
    drawChart () {
      var myChart = this.$echarts.init(document.getElementById('myChart3'), 'walden')
      let option = {
        title: {
          text: this.title,
          left: 'center'
        },
        tooltip: {
          trigger: 'item',
          formatter: '{a} <br/>{b} : {c} ({d}%)'
        },
        legend: {
          left: 'center',
          top: 'bottom',
          data: this.text
        },
        series: [
          {
            name: '面积模式',
            type: 'pie',
            radius: [20, this.radius],
            center: ['50%', '60%'],
            roseType: 'area',
            data: this.digitalData
          }
        ]
      }

      myChart.setOption(option, true)
    }
  }
}
</script>

<style lang='scss' scoped>
</style>

数字字体是液晶的数字字体ttf,百度找得到,在app.vue入口写好:

@font-face {
  font-family: 'Digital';
  src: url('assets/font/Digital.ttf');
}

最后就是该页面的代码了(四百多行): 

<template>
  <div class="back">
    <div class="top">
      <div>大厅已服务监视 {{watchTime.toFixed(1)}} 小时 (h)</div>
      <img src="../assets/winwatch/top.png" alt="">
      <div class="title">资源共享监视平台</div>
      <img src="../assets/winwatch/top.png" alt="">
      <div class="time">
        <div>{{time}}</div>
        <div>{{date}}</div>
      </div>
      <div @click="toPageBack">返回<img src="../assets/winwatch/back.png" width="30px" alt=""></div>
      <div @click="fullScreen(screenAll)">
        <span v-if="screenAll == 0">进入全屏</span>
        <span v-if="screenAll == 1">退出全屏</span>
      </div>
    </div>
    <el-row>
      <el-col :span="15">
        <div class="item-left-top">
          <div><chart2 :width='380' :height='250' :leftText="chart2Text" :digitalData="digitalData"
            style="padding-top: 20px;"></chart2></div>
          <div>
            <div>轮播广告图点击量</div>
            <div>100</div>
            <div>昨日点击&nbsp;&nbsp;&nbsp;100</div>
            <div>对比点击&nbsp;&nbsp;&nbsp;0</div>
          </div>
          <div>
            <div>在线用户</div>
            <div>100</div>
            <div>平台资源数&nbsp;&nbsp;&nbsp;100</div>
            <div>今日资源点击量&nbsp;&nbsp;90008</div>
          </div>
        </div>
        <div class="item-left-bottom">
          <div>
            <p>活跃用户前五所在城市</p>
            <chart3 :width='340' :height='340' :radius='80' :leftText="chart3Text" :digitalData="digitalData2"></chart3>
          </div>
          <div>
            <p>活跃用户前五所在城市</p>
            <table border="1" cellpadding="0" cellspacing="0" width="90%" class="table1">
              <tr height="50px" align="center" style="font-size:15px;">
                <td>分类</td>
                <td>名称</td>
                <td>下载量</td>
              </tr>
              <tr v-for="(item, index) in tableData1" :key="index" height="40px" align="center">
                <td>{{item.sortName}}</td>
                <td>{{item.title}}</td>
                <td>{{item.downloadNum}}</td>
              </tr>
            </table>
          </div>
        </div>
      </el-col>
      <el-col :span="9">
        <div class="item-right">
          <p>近七天资源下载量</p>
          <chart1 :width='400' :height='280' :xAxisText="xAxisText1"
            :xFontColor="'#FFFFFF'" :digitalData="digitalData1"></chart1>
          <p>排名前 8 资源 <br> 更新于2020-06-11</p>
          <table border="1" cellpadding="0" cellspacing="0" width="90%" class="table2">
            <tr height="50px" align="center" style="font-size:15px;">
              <td>分类</td>
              <td>名称</td>
              <td>下载量</td>
            </tr>
            <tr v-for="(item, index) in tableData1" :key="index" height="40px" align="center">
              <td>{{item.sortName}}</td>
              <td>{{item.title}}</td>
              <td>{{item.downloadNum}}</td>
            </tr>
          </table>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import moment from 'moment'
import chart1 from '@/components/chart1'
import chart2 from '@/components/chart2'
import chart3 from '@/components/chart3'
export default {
  components: {
    chart1,
    chart2,
    chart3
  },
  data () {
    return {
      screenAll: 0, // 0退出全屏, 1全屏
      time: '',
      watchTime: 0,
      digitalData1: [1, 2, 3, 4, 10, 5, 1],
      xAxisText1: ['07-18', '07-19', '07-20', '07-21', '07-22', '07-23', '07-24'],
      chart2Text: ['广州市', '佛山市', '深圳市', '上海市', '北京市'],
      digitalData: [
        {value: 200, name: '广州市'},
        {value: 100, name: '佛山市'},
        {value: 100, name: '深圳市'},
        {value: 50, name: '上海市'},
        {value: 50, name: '北京市'}
      ],
      chart3Text: ['广州市', '佛山市', '深圳市', '上海市', '北京市'],
      digitalData2: [
        {value: 200, name: '广州市'},
        {value: 100, name: '佛山市'},
        {value: 100, name: '深圳市'},
        {value: 50, name: '上海市'},
        {value: 50, name: '北京市'}
      ],
      tableData1: [{sortName: '电影', title: '唐人街探案 II', downloadNum: 1866},
        {sortName: '电影', title: '唐人街探案 II', downloadNum: 1866},
        {sortName: '电影', title: '唐人街探案 II', downloadNum: 1866},
        {sortName: '电影', title: '唐人街探案 II', downloadNum: 1866},
        {sortName: '电影', title: '唐人街探案 II', downloadNum: 1866}]
    }
  },
  mounted () {
    this.timer = setInterval(() => { // 更新小时时间
      this.time = moment().format('HH:mm:ss')
    }, 1000)
    this.watchTimer = setInterval(() => { // 更新监测时间
      this.watchTime += 0.1
    }, 360000)
  },
  beforeDestroy () { // 清除定时器
    if (this.timer) {
      clearInterval(this.timer)
    }
    if (this.watchTimer) {
      clearInterval(this.watchTimer)
    }
  },
  methods: {
    toPageBack () {
      this.$router.go(-1)
    },
    fullScreen () { // # 全屏显示
      if (this.screenAll === 1) {
        this.screenAll = 0
        if (document.exitFullscreen) {
          document.exitFullscreen()
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen()
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen()
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen()
        }
      } else {
        this.screenAll = 1
        if (document.documentElement.requestFullscreen) {
          document.documentElement.requestFullscreen()
        } else if (document.documentElement.webkitRequestFullScreen) {
          document.documentElement.webkitRequestFullScreen()
        } else if (document.documentElement.mozRequestFullScreen) {
          document.documentElement.mozRequestFullScreen()
        } else if (document.documentElement.msRequestFullscreen) {
          // IE11
          document.documentElement.msRequestFullscreen()
        }
      }
    }
  },
  computed: {
    date () {
      return moment().format('YYYY 年 MM 月 DD 日')
    }
  }
}
</script>

<style lang="scss" scoped>
tr:hover{
  background: #030237;
}
.back{
  background: #030237;
  width: 100%;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  font-size: 18px;
  overflow-x: hidden;
  color: #5A95DA;
  .top{
    width: 100%;
    height: 60px;
    line-height: 60px;
    color: #4471A6;
    // background: #050297;
    border-bottom: 2px solid #4471A6;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 1400px;
    position: relative;
    div:first-child{
      position: relative;
      left: -3%;
    }
    img:nth-child(2){
      width: 250px;
      height: 40px;
      margin-left: 2%;
    }
    img:nth-child(4){
      width: 250px;
      height: 40px;
    }
    .title{
      width: 280px;
      background-image: url('../assets/winwatch/top2.png');
      background-size: 100% 100%;
      background-repeat: no-repeat;
      text-align: center;
    }
    .time{
      width: 200px;
      height: 50px;
      line-height: 25px;
      display: flex;
      flex-direction: column;
      div{
        text-align: center;
        font-weight: 600;
        font-size: 18px;
        font-family: Digital;
      }
    }
    div:nth-child(6){
      cursor: pointer;
      img{
        position: relative;
        top: 5px;
        margin-left: 5px;
      }
    }
    div:last-child{
      font-size: 12px;
      margin-left: 2%;
      cursor: pointer;
    }
    div:last-child:hover{
      color: cyan;
    }
  }
  .el-row{
    .item-left-top{
      width: 100%;
      height: 350px;
      display: flex;
      justify-content: center;
      align-items: center;
      // background: crimson;
      div{
        width: 26%;
        height: 280px;
        // background: cornflowerblue;
        margin: auto;
        display: flex;
        flex-direction: column;
        position: relative;
        left: 1%;
      }
      div:first-child{
        width: 400px;
        height: 280px;
      }
      div:nth-child(2), div:last-child{
        animation: dh1 5s;
        -webkit-animation: dh1 5s; /* Safari and Chrome */
        div{
          width: 100%;
          display: flex;
          justify-content: center;
          text-align: center;
          font-family: digital;
        }
        div:nth-child(2){
          font-size: 80px;
          padding: 30px 0;
          color: #D3EDFF;
        }
        div:nth-child(3), div:last-child{
          text-align: left;
          text-indent: 30px;
        }
      }
    }
    .item-left-bottom{
      width: 96%;
      height: 400px;
      margin: auto;
      border: 2px solid #0094FF;
      border-radius: 10px;
      margin-bottom: 30px;
      background-image: radial-gradient(#1A2D5E 5%, #000337 70%);
      display: flex;
      justify-content: center;
      align-items: center;
      animation: dh2 2s;
      -webkit-animation: dh2 2s; /* Safari and Chrome */
      animation-delay: 2s;
      animation-fill-mode: both;
      div{
        height: 380px;
        // background: crimson;
        margin: 0 10px;
        p{
          position: relative;
          top: 30px;
        }
      }
      div:first-child{
        width: 340px;
        display: flex;
        flex-direction: column;
        align-items: center;
        div{
          position: relative;
          bottom: 8%;
          animation: dh4 2s;
          -webkit-animation: dh4 2s; /* Safari and Chrome */
          animation-delay: 3s;
          animation-fill-mode: both;
        }
      }
      div:last-child{
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
      }
      .table1{
        position: relative;
        top: 50px;
        border: 1px solid #5A95DA;
        font-size: 12px;
        animation: dh4 2s;
        -webkit-animation: dh4 2s; /* Safari and Chrome */
        animation-delay: 5s;
        animation-fill-mode: both;
      }
    }
    .item-right{
      width: 90%;
      height: 700px;
      margin: 40px auto;
      border: 2px solid #0094FF;
      border-radius: 10px;
      background-image: linear-gradient(to top, #1A2D5E, #000337);
      animation: dh3 2s;
      -webkit-animation: dh3 2s; /* Safari and Chrome */
      animation-delay: 4s;
      animation-fill-mode: both;
      div{
        position: relative;
        left: 5%;
        animation: dh4 2s;
        -webkit-animation: dh4 2s; /* Safari and Chrome */
        animation-delay: 6s;
        animation-fill-mode: both;
      }
      .table2{
        border: 1px solid #5A95DA;
        font-size: 12px;
        margin: 30px auto;
        animation: dh4 2s;
        -webkit-animation: dh4 2s; /* Safari and Chrome */
        animation-delay: 7s;
        animation-fill-mode: both;
      }
      p{
        padding-top: 40px;
        font-size: 15px;
        text-align: center;
      }
      p:first-child{
        padding-top: 20px;
        margin: 0;
      }
    }
  }
}
// 渐变效果
@keyframes dh1{
  from {opacity: 0;}
  to {opacity: 1;}
}

// 上移效果
@keyframes dh2{
  from {opacity: 0; position: relative;top: 100px;}
  to {opacity: 1; position: relative; top: 0;}
}

// 左移效果
@keyframes dh3{
  from {opacity: 0; position: relative;left: 500px;}
  to {opacity: 1; position: relative; left: 0;}
}

// 缩放出现效果
@keyframes dh4{
  from {opacity: 0; transform: scale(0,0);}
  to {opacity: 1; transform: scale(1,1);}
}
</style>

效果就是上面图片那样了,Good Luck !!

  • 9
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LINGK98

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值