欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue使用Echarts實現(xiàn)橫向柱狀圖,并通過WebSocket即時通訊更新

 更新時間:2023年03月27日 15:01:33   作者:進階的巨人001  
這篇文章主要介紹了Vue使用Echarts實現(xiàn)橫向柱狀圖,并通過WebSocket即時通訊更新方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

先看下效果圖

并且數(shù)據(jù)每隔3秒自動變換一次

先看下后臺返回的數(shù)據(jù)結(jié)構(gòu)是什么樣子的

[
  {
    "name":"商家1",
    "value":"99"
  },
  {
    "name":"商家2",
    "value":"199"
  },
  {
    "name":"商家3",
    "value":"222"
  },
  {
    "name":"商家4",
    "value":"99"
  },
  {
    "name":"商家5",
    "value":"499"
  },
  {
    "name":"商家6",
    "value":"252"
  },
  {
    "name":"商家7",
    "value":"199"
  },
  {
    "name":"商家8",
    "value":"29"
  },
  {
    "name":"商家9",
    "value":"232"
  },{
    "name":"商家10",
    "value":"99"
  },
  {
    "name":"商家11",
    "value":"77"
  },
  {
    "name":"商家12",
    "value":"82"
  },
  {
    "name":"商家13",
    "value":"99"
  },
  {
    "name":"商家14",
    "value":"19"
  },
  {
    "name":"商家15",
    "value":"22"
  },
  {
    "name":"商家16",
    "value":"522"
  }
]

開始實現(xiàn)前端的代碼

html

<div class="com-page">
<div class="com-container">
  <div class="com-chart" ref="seller_ref"></div>
</div>
</div>

css

html,body,#app{
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
}
.com-page {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.com-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.com-chart {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

data

data() {
    return {
      chartInstance: null,  //初始化echartInstance對象
      allData: null,    //接收的后臺數(shù)據(jù)
      currentPage: 1, //當前顯示的頁數(shù)
      totalPage: 0, //一共有多少頁
      timerId: null //定時器標識
    }
  },

methods

initChart方法

initChart() {
     //初始化echartInstance對象
     //chalk是我們定義的主題,echarts官方有案例,怎么使用可以百度一下,不喜歡可以直接刪掉
      this.chartInstance = this.$echarts.init(this.$refs.seller_ref, 'chalk')
      //對圖表初始化配置對控制
      const initOption = {
        title: {
          text: '▎商家銷售統(tǒng)計',
          left: 20,
          top: 20
        },
        grid: {
          top: '20%',
          left: '3%',
          right: '6%',
          bottom: '3%',
          containLabel: true // 距離是包含坐標軸上的文字
        },
        xAxis: {
          type: 'value'
        },
        yAxis: {
          type: 'category'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'line',
            z: 0,
            lineStyle: {
              color: '#2D3443'
            }
          }
        },
        series: [{
          type: 'bar',
          label: {
            show: true,
            position: 'right',
            textStyle: {
              color: 'white'
            }
          },
          itemStyle: {
            // 指明顏色漸變的方向
            // 指明不同百分比之下顏色的值
            color: new this.$echarts.graphic.LinearGradient(0, 0, 1, 0, [
              // 百分之0狀態(tài)之下的顏色值
              {
                offset: 0,
                color: '#5052EE'
              },
              // 百分之100狀態(tài)之下的顏色值
              {
                offset: 1,
                color: '#AB6EE5'
              }
            ])
          }
        }]
      }
      this.chartInstance.setOption(initOption)
      //對圖表對象進行鼠標事件監(jiān)聽
      //鼠標移入,定時器停止
      this.chartInstance.on('mouseover', () => {
        clearInterval(this.timerId)
      })
      //鼠標移出,定時器開始
      this.chartInstance.on('mouseout', () => {
        this.startInterval()
      })
    },

getData方法

這里還是用http請求獲取的數(shù)據(jù),后面我再講怎么用WebSocket獲取我們的數(shù)據(jù)

 async getData() {
      const {
        data: res
      } = await this.$http.get('seller')
      this.allData = res
      //對數(shù)據(jù)進行排序
      this.allData.sort((a, b) => {
        return a.value - b.value //從小到大排序
      })
      //每五個元素顯示一頁
      this.totalPage = this.allData.length % 5 === 0 ? this.allData.length / 5 : this.allData.length / 5 + 1
      this.updateChart()
      //啟動定時器
      this.startInterval()
    },

updateChart方法

//更新圖表
    updateChart() {
      //起始的位置
      const start = (this.currentPage - 1) * 5 
      //結(jié)束的位置
      //起始為0,所以展示1-5
      const end = this.currentPage * 5 
      const showData = this.allData.slice(start, end)
      const sellerNames = showData.map((item) => {
        return item.name
      })
      const sellerValue = showData.map((item) => {
        return item.value
      })
      const dataOption = {
        yAxis: {
          data: sellerNames
        },
        series: [{
          data: sellerValue
        }]
      }
      this.chartInstance.setOption(dataOption)
    },

startInterval方法

//定時器,數(shù)據(jù)每3秒更新一次
 startInterval() {
      if (this.timerId) {
        clearInterval(this.timerId)
      }
      this.timerId = setInterval(() => {
        this.currentPage++
        if (this.currentPage > this.totalPage) {
          this.currentPage = 1
        }
        this.updateChart()
      }, 3000)
    },

screenAdapter方法

 //屏幕適配
    screenAdapter() {
      const titleFontSize = this.$refs.seller_ref.offsetWidth / 100 * 3.6
      console.log(titleFontSize)
      const adapterOption = {
        title: {
          textStyle: {
            fontSize: titleFontSize
          }
        },
        tooltip: {
          axisPointer: {
            lineStyle: {
              width: titleFontSize
            }
          }
        },
        series: [{
          barWidth: titleFontSize,
          //圓角大小
          itemStyle: {
            barBorderRadius: [0, titleFontSize / 2, titleFontSize / 2, 0],
          }
        }]
      }
      this.chartInstance.setOption(adapterOption)
      //手動調(diào)用圖表對象resize
      this.chartInstance.resize()
    }

mounted

  mounted() {
    this.initChart()
    this.getData()
    window.addEventListener('resize', this.screenAdapter)
    this.screenAdapter()
  },

destroyed

  destroyed() {
    clearInterval(this.timerId)
    window.removeEventListener('resize', this.screenAdapter)
  },

好了,完事

下面我把如何用WebSocket獲取數(shù)據(jù)說一下

封裝了一個WebSocket

export default class SocketService {
  /**
   * 單例
   */
  static instance = null
  static get Instance() {
    if (!this.instance) {
      this.instance = new SocketService()
    }
    return this.instance
  }

  // 和服務端連接的socket對象
  ws = null

  // 存儲回調(diào)函數(shù)
  callBackMapping = {}

  // 標識是否連接成功
  connected = false

  // 記錄重試的次數(shù)
  sendRetryCount = 0

  // 重新連接嘗試的次數(shù)
  connectRetryCount = 0

  //  定義連接服務器的方法
  connect() {
    // 連接服務器
    if (!window.WebSocket) {
      return console.log('您的瀏覽器不支持WebSocket')
    }
    this.ws = new WebSocket('ws://localhost:9998')

    // 連接成功的事件
    this.ws.onopen = () => {
      console.log('連接服務端成功了')
      this.connected = true
      // 重置重新連接的次數(shù)
      this.connectRetryCount = 0
    }
    // 1.連接服務端失敗
    // 2.當連接成功之后, 服務器關閉的情況
    this.ws.onclose = () => {
      console.log('連接服務端失敗')
      this.connected = false
      this.connectRetryCount++
      setTimeout(() => {
        this.connect()
      }, 500 * this.connectRetryCount)
    }
    // 得到服務端發(fā)送過來的數(shù)據(jù)
    this.ws.onmessage = msg => {
      console.log('從服務端獲取到了數(shù)據(jù)')
      // 真正服務端發(fā)送過來的原始數(shù)據(jù)時在msg中的data字段
      // console.log(msg.data)
      const recvData = JSON.parse(msg.data)
      const socketType = recvData.socketType
      // 判斷回調(diào)函數(shù)是否存在
      if (this.callBackMapping[socketType]) {
        const action = recvData.action
        if (action === 'getData') {
          const realData = JSON.parse(recvData.data)
          this.callBackMapping[socketType].call(this, realData)
        } else if (action === 'fullScreen') {
          this.callBackMapping[socketType].call(this, recvData)
        } else if (action === 'themeChange') {
          this.callBackMapping[socketType].call(this, recvData)
        }
      }
    }
  }

  // 回調(diào)函數(shù)的注冊
  registerCallBack (socketType, callBack) {
    this.callBackMapping[socketType] = callBack
  }

  // 取消某一個回調(diào)函數(shù)
  unRegisterCallBack (socketType) {
    this.callBackMapping[socketType] = null
  }

  // 發(fā)送數(shù)據(jù)的方法
  send (data) {
    // 判斷此時此刻有沒有連接成功
    if (this.connected) {
      this.sendRetryCount = 0
      this.ws.send(JSON.stringify(data))
    } else {
      this.sendRetryCount++
      setTimeout(() => {
        this.send(data)
      }, this.sendRetryCount * 500)
    }
  }
}

在main.js中進行連接,掛載原型

//對服務端進行連接
import SocketService from '../utils/socket_service'
SocketService.Instance.connect()
// 其他的組件  this.$socket
Vue.prototype.$socket = SocketService.Instance

然后在組件中

  created() {
    //在組件創(chuàng)建完成之后進行回調(diào)函數(shù)注冊
    this.$socket.registerCallBack('trendData',this.getData)
  },
  
   mounted() {
    this.initChart();
    //發(fā)送數(shù)據(jù)給服務器,告訴服務器,我現(xiàn)在需要數(shù)據(jù)
    this.$socket.send({
      action:'getData',
      socketType:'trendData',
      chartName:'trend',
      value:''
    })
    window.addEventListener("resize", this.screenAdapter);
    this.screenAdapter();
  },
  
  destroyed() {
    window.removeEventListener("resize", this.screenAdapter);
    //取消
    this.$socket.unRegisterCallBack('trendData')
  },
  methods:{
  //res就是服務端發(fā)送給客戶端的圖表數(shù)據(jù)
    getData(res) {
      this.allData = res;
      this.updateChart();
    },
    }

這樣就實現(xiàn)了后端發(fā)生變化,前端即時更新視圖

至于為什么WebSocket這樣封裝,因為后臺定了規(guī)則

const path = require('path')
const fileUtils = require('../utils/file_utils')
const WebSocket = require('ws')
// 創(chuàng)建WebSocket服務端的對象, 綁定的端口號是9998
const wss = new WebSocket.Server({
  port: 9998
})
// 服務端開啟了監(jiān)聽
module.exports.listen = () => {
  // 對客戶端的連接事件進行監(jiān)聽
  // client:代表的是客戶端的連接socket對象
  wss.on('connection', client => {
    console.log('有客戶端連接成功了...')
    // 對客戶端的連接對象進行message事件的監(jiān)聽
    // msg: 由客戶端發(fā)給服務端的數(shù)據(jù)
    client.on('message',async msg => {
      console.log('客戶端發(fā)送數(shù)據(jù)給服務端了: ' + msg)
      let payload = JSON.parse(msg)
      const action = payload.action
      if (action === 'getData') {
        let filePath = '../data/' + payload.chartName + '.json'
        // payload.chartName // trend seller map rank hot stock
        filePath = path.join(__dirname, filePath)
        const ret = await fileUtils.getFileJsonData(filePath)
        // 需要在服務端獲取到數(shù)據(jù)的基礎之上, 增加一個data的字段
        // data所對應的值,就是某個json文件的內(nèi)容
        payload.data = ret
        client.send(JSON.stringify(payload))
      } else {
        // 原封不動的將所接收到的數(shù)據(jù)轉(zhuǎn)發(fā)給每一個處于連接狀態(tài)的客戶端
        // wss.clients // 所有客戶端的連接
        wss.clients.forEach(client => {
          client.send(msg)
        })
      }
      // 由服務端往客戶端發(fā)送數(shù)據(jù)
      // client.send('hello socket from backend')
    })
  })
}

有不懂的可以去我的github查看源代碼,前后端都有,后端必須啟動,前端才有顯示,WebSocket我只配了Trend組件,其他全部一樣的操作

github項目地址https://github.com/lsh555/Echarts

項目詳情如下

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • 詳解Vue打包優(yōu)化之code spliting

    詳解Vue打包優(yōu)化之code spliting

    這篇文章主要介紹了詳解Vue打包優(yōu)化之code spliting,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 深入淺出vue圖片路徑的實現(xiàn)

    深入淺出vue圖片路徑的實現(xiàn)

    這篇文章主要介紹了深入淺出vue圖片路徑的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • vue Tab切換以及緩存頁面處理的幾種方式

    vue Tab切換以及緩存頁面處理的幾種方式

    相信tab切換對于大家來說都不算陌生,后臺管理系統(tǒng)中多會用到。如果不知道的話,可以看一下瀏覽器上方的標簽頁切換,大概效果就是這樣。
    2021-05-05
  • Vue中自定義標簽及其使用方式

    Vue中自定義標簽及其使用方式

    這篇文章主要介紹了Vue中自定義標簽及其使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Vue.js@2.6.10更新內(nèi)置錯誤處機制Fundebug同步支持相應錯誤監(jiān)控

    Vue.js@2.6.10更新內(nèi)置錯誤處機制Fundebug同步支持相應錯誤監(jiān)控

    這篇文章主要介紹了Vue.js@2.6.10更新內(nèi)置錯誤處機制,F(xiàn)undebug同步支持相應錯誤監(jiān)控 ,需要的朋友可以參考下
    2019-05-05
  • vue2.0全局組件之pdf詳解

    vue2.0全局組件之pdf詳解

    這篇文章主要為大家詳細紹了vue2.0全局組件之pdf的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • vue-prop父組件向子組件進行傳值的方法

    vue-prop父組件向子組件進行傳值的方法

    下面小編就為大家分享一篇vue-prop父組件向子組件進行傳值的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue使用mpegts.js實現(xiàn)播放flv的直播視頻流

    vue使用mpegts.js實現(xiàn)播放flv的直播視頻流

    這篇文章主要為大家詳細介紹了vue如何使用mpegts.js實現(xiàn)播放flv的直播視頻流,文中的示例代碼講解詳細,有需要的小伙伴可以參考一下
    2024-01-01
  • Vue配置文件中的proxy配置方式詳解

    Vue配置文件中的proxy配置方式詳解

    今天被vue中proxy配置困擾了一天,記錄一下,下面這篇文章主要給大家介紹了關于Vue配置文件中的proxy配置方式的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-06-06
  • SpringBoot實現(xiàn)全局和局部跨域的兩種方式

    SpringBoot實現(xiàn)全局和局部跨域的兩種方式

    本文主要介紹了SpringBoot實現(xiàn)全局和局部跨域的兩種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01

最新評論