热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Vue中Echarts实现横向柱状图,并且通过WebSocket即时通讯更新

先看下效果图,并且数据每隔3秒自动变换一次先看下后台返回的数据结构是什么样子的[{name:商家1,value:99},{name:商家2,

先看下效果图,并且数据每隔3秒自动变换一次
在这里插入图片描述
先看下后台返回的数据结构是什么样子的

[{"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"}
]

好了,开始实现前端的代码

html





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, //接收的后台数据currentPage: 1, //当前显示的页数totalPage: 0, //一共有多少页timerId: null //定时器标识}},

methods

initChart方法

initChart() {//初始化echartInstance对象//chalk是我们定义的主题,echarts官方有案例,怎么使用可以百度一下,不喜欢可以直接删掉this.chartInstance = this.$echarts.init(this.$refs.seller_ref, 'chalk')//对图表初始化配置对控制const initOption = {title: {text: '▎商家销售统计',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状态之下的颜色值{offset: 0,color: '#5052EE'},// 百分之100状态之下的颜色值{offset: 1,color: '#AB6EE5'}])}}]}this.chartInstance.setOption(initOption)//对图表对象进行鼠标事件监听//鼠标移入,定时器停止this.chartInstance.on('mouseover', () => {clearInterval(this.timerId)})//鼠标移出,定时器开始this.chartInstance.on('mouseout', () => {this.startInterval()})},

getData方法

这里还是用http请求获取的数据,后面我再讲怎么用WebSocket获取我们的数据

async getData() {const {data: res} = await this.$http.get('seller')this.allData = res//对数据进行排序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 + 1this.updateChart()//启动定时器this.startInterval()},

updateChart方法

//更新图表updateChart() {//起始的位置const start = (this.currentPage - 1) * 5 //结束的位置//起始为0,所以展示1-5const 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方法

//定时器,数据每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.6console.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)//手动调用图表对象resizethis.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获取数据说一下

封装了一个WebSocket

export default class SocketService {/*** 单例*/static instance = nullstatic get Instance() {if (!this.instance) {this.instance = new SocketService()}return this.instance}// 和服务端连接的socket对象ws = null// 存储回调函数callBackMapping = {}// 标识是否连接成功connected = false// 记录重试的次数sendRetryCount = 0// 重新连接尝试的次数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// 重置重新连接的次数this.connectRetryCount = 0}// 1.连接服务端失败// 2.当连接成功之后, 服务器关闭的情况this.ws.onclose = () => {console.log('连接服务端失败')this.connected = falsethis.connectRetryCount++setTimeout(() => {this.connect()}, 500 * this.connectRetryCount)}// 得到服务端发送过来的数据this.ws.onmessage = msg => {console.log('从服务端获取到了数据')// 真正服务端发送过来的原始数据时在msg中的data字段// console.log(msg.data)const recvData = JSON.parse(msg.data)const socketType = recvData.socketType// 判断回调函数是否存在if (this.callBackMapping[socketType]) {const action = recvData.actionif (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)}}}}// 回调函数的注册registerCallBack (socketType, callBack) {this.callBackMapping[socketType] = callBack}// 取消某一个回调函数unRegisterCallBack (socketType) {this.callBackMapping[socketType] = null}// 发送数据的方法send (data) {// 判断此时此刻有没有连接成功if (this.connected) {this.sendRetryCount = 0this.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() {//在组件创建完成之后进行回调函数注册this.$socket.registerCallBack('trendData',this.getData)},mounted() {this.initChart();//发送数据给服务器,告诉服务器,我现在需要数据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就是服务端发送给客户端的图表数据getData(res) {this.allData = res;this.updateChart();},}

这样就实现了后端发生变化,前端即时更新视图

至于为什么WebSocket这样封装,因为后台定了规则

const path = require('path')
const fileUtils = require('../utils/file_utils')
const WebSocket = require('ws')
// 创建WebSocket服务端的对象, 绑定的端口号是9998
const wss = new WebSocket.Server({port: 9998
})
// 服务端开启了监听
module.exports.listen = () => {// 对客户端的连接事件进行监听// client:代表的是客户端的连接socket对象wss.on('connection', client => {console.log('有客户端连接成功了...')// 对客户端的连接对象进行message事件的监听// msg: 由客户端发给服务端的数据client.on('message',async msg => {console.log('客户端发送数据给服务端了: ' + msg)let payload = JSON.parse(msg)const action = payload.actionif (action === 'getData') {let filePath = '../data/' + payload.chartName + '.json'// payload.chartName // trend seller map rank hot stockfilePath = path.join(__dirname, filePath)const ret = await fileUtils.getFileJsonData(filePath)// 需要在服务端获取到数据的基础之上, 增加一个data的字段// data所对应的值,就是某个json文件的内容payload.data = retclient.send(JSON.stringify(payload))} else {// 原封不动的将所接收到的数据转发给每一个处于连接状态的客户端// wss.clients // 所有客户端的连接wss.clients.forEach(client => {client.send(msg)})}// 由服务端往客户端发送数据// client.send('hello socket from backend')})})
}

有不懂的可以去我的github查看源代码,前后端都有,后端必须启动,前端才有显示,WebSocket我只配了Trend组件,其他全部一样的操作

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

项目详情如下

在这里插入图片描述


推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • HTML5网页模板怎么加百度统计?
    本文介绍了如何在HTML5网页模板中加入百度统计,并对模板文件、css样式表、js插件库等内容进行了说明。同时还解答了关于HTML5网页模板的使用方法、表单提交、域名和空间的问题,并介绍了如何使用Visual Studio 2010创建HTML5模板。此外,还提到了使用Jquery编写美好的HTML5前端框架模板的方法,以及制作企业HTML5网站模板和支持HTML5的CMS。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
  • CSS3 animation动画属性详解及用法
    本文详细介绍了CSS3 animation动画的各种属性及用法,包括关键帧动画、动画名称、动画时间、动画曲线、动画延迟、动画播放次数、动画状态和动画前后的状态等。通过本文的学习,读者可以深入了解CSS3 animation动画的使用方法。 ... [详细]
  • 使用圣杯布局模式实现网站首页的内容布局
    本文介绍了使用圣杯布局模式实现网站首页的内容布局的方法,包括HTML部分代码和实例。同时还提供了公司新闻、最新产品、关于我们、联系我们等页面的布局示例。商品展示区包括了车里子和农家生态土鸡蛋等产品的价格信息。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • 本文介绍了在HTML中实现表格的页眉页脚布局的解决方案。通过基本的HTML/CSS技术,避免使用内联样式和固定定位,实现了一个标准的页眉页脚布局。提供了一个替代的解决方案,为读者提供了参考。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 本文介绍了如何在Jquery中通过元素的样式值获取元素,并将其赋值给一个变量。提供了5种解决方案供参考。 ... [详细]
  • mui框架offcanvas侧滑超出部分隐藏无法滚动如何解决
    web前端|js教程off-canvas,部分,超出web前端-js教程mui框架中off-canvas侧滑的一个缺点就是无法出现滚动条,因为它主要用途是设置类似于qq界面的那种格 ... [详细]
  • 之前一直都知道css中的部分元素具有包裹性,今天写博客的时候正好也遇到了一个,所以想总结一下,有错误的地方欢迎指出来。什么是包裹性?包裹性就是父元素的宽度会收缩到和内部元素宽度一样 ... [详细]
  • 我用Tkinter制作了一个图形用户界面,有两个主按钮:“开始”和“停止”。请您就如何使用“停止”按钮终止“开始”按钮为以下代码调用的已运行功能提供建议 ... [详细]
  • ORACLE空间管理实验5:块管理之ASSM下高水位的影响
    数据库|mysql教程ORACLE,空间,管理,实验,ASSM,下高,水位,影响,数据库-mysql教程易语言黑客软件源码,vscode左侧搜索,ubuntu怎么看上一页,ecs搭 ... [详细]
  • 前端开发工程师必读书籍有哪些值得推荐?我们直接进入代码复杂版式设置,如下所示,先写些标签,源码在这个链接里面:https://codepen.io/Shadid ... [详细]
author-avatar
我怎么了2602902235
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有