经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Echarts » 查看文章
在echaerts中渲染50万条数据的优化方案
来源:cnblogs  作者:ZihangChu  时间:2023/3/22 9:29:07  对本文有异议

背景:项目需求中要在页面上渲染大约50万条左右的波形数据图表

 

 那么如何解决渲染中的卡顿呢?

肯定是要从服务端和前端一起优化这是毋庸置疑的。

1.服务端:

服务端耗时最多的一定是在数据库的筛选数据的行为上,本次需求中数据的筛选是根据物理量的类型和时间来进行的。

为了提速,应当取消掉其他的筛选条件,并且使用mongodb和redis,还应该将数据分片发送给前端。

2.前端:

首先我们要搞清楚,优化策略的重点是在数据的拿取上,因为渲染的速度其实远快于数据交互的速度,要想提速首先要解决的是短板。

在数据拿取时我们应当进行轮询,分片的拿到服务端传输的数据,然后进行渲染。

我们来整理一下思路:

1.第一次轮询结束拿到数据后,我们需要进行绘图。然后判断是否进行下一次轮询

2.第二次轮询结束之后我们需要将拿到的数据,append到图表之中,然后判断否进行下一次轮询

3.如何随时的让轮询终止。

这三个就是目前我们需要解决的问题点。

第一次拿到数据之后我们判断数据的长度是否为0,为0则终止轮询,不为0则继续。

后面继续轮询时,每次轮询拿到数据都要判断图表是否存在,存在就dispose,然后重绘。

要注意的点时,我们的图表是可以缩放的,所以在重绘时还需要将缩放条的位置进行记录,然后设置到datazoom里面,这样可以提高用户体验。

下面贴出代码:

  1. getListWaveformDat(count) {
  2.  
  3. this.loading = true;//加载loading动画
  4.  
  5. //获取波形图数据
  6. getListWaveformDat({
  7. deviceId: this.queryPointParams.deviceId,
  8. diId: this.diId,
  9. reportedOn: this.orgTime,
  10. keyName: this.dataAxis,
  11. num: this.pageNum,
  12. size: 10000,
  13. count: count ? count : '',
  14. }).then((res) => {
  15. if (res.length > 0) {
  16. this.noData = false//是否加载缺省值图片
  17. console.log(this.orgchart)
  18. if (this.orgchart) {
  19. this.orgchart.dispose();
  20. }
  21. this.oscillograph = res;
  22. let x = [];
  23. for (let i = 0; i < this.oscillograph.length; i++) {
  24. x[i] = this.oscillograph[i].count;
  25. }//处理X轴数据
  26.  
  27. let y = [];
  28. for (let i = 0; i < this.oscillograph.length; i++) {
  29. y[this.oscillograph[i].count * 1 - 1] = this.oscillograph[i].value * 1
  30. }
  31. for (let i = 0; i < this.oscillographY.length; i++) {
  32. if (this.oscillographY[i] == undefined) {
  33. if (y[i]) {
  34. this.oscillographY[i] = y[i]
  35. }
  36. }
  37. }//处理Y轴数据
  38. console.log(this.oscillographY)
  39. this.pageNum = this.pageNum + 1;//轮询次数加1
  40. this.$nextTick(() => {
  41. this.orgDraw();//绘制图表
  42.  
  43. })
  44.  
  45. this.loading = false;//关闭加载loading
  46. this.getListWaveformDat(x[x.length - 1])//继续轮询
  47.  
  48. }
  49. else {
  50. //如果加载的数据为空
  51. this.loading = false;
  52. console.log(this.orgchart)
  53. if (this.pageNum == 1) {
  54. //如果第一次轮询就为空,加载缺省图片
  55. this.noData = true;
  56. if (this.orgchart) {
  57. this.orgchart.dispose();//清除上一次加载的图表
  58.  
  59.  
  60. }
  61. this.pageNum = 1;//请求完所有数据之后初始化一下
  62. return
  63.  
  64. }
  65.  
  66. });
  67.  
  68. },

  

 

 

 这是接口返回的数据源,X就是count,Y就是Value。因为每次轮询查到的数据都是乱序的,但是图表要求X,Y必须对应所以需要对数据进行重新排序。

思路:1.先获取X轴的长度,然后根据长度生成X,Y两个数组。2.将Y数组的值都设置为undefined,X数组的值设为1-X的长度3.遍历接口的数据,将count作为Y的索引,将value塞入对应的元素中。

  1. getX() {
  2. getMaxCount(
  3. {
  4. deviceId: this.queryPointParams.deviceId,
  5. reportedOn: this.orgTime,
  6. keyName: this.dataAxis,
  7. }
  8. ).then((res) => {
  9. console.log(res, '======')
  10. this.oscillographX = Array.from({ length: res * 1 }, (value, key) => key + 1)
  11. this.oscillographY = Array.from({ length: res * 1 }, (value, key) => undefined)
  12. console.log(this.oscillographX);
  13. })
  14. },

  处理X,Y轴数据的代码在第一个代码块中已经有就不贴了。

完成数据处理之后就是进行绘图。

  1. orgDraw() {
  2. let that = this;
  3. if (this.orgchart) {
  4. this.orgchart.dispose();
  5. }
  6. console.log(this.start, this.end, 'xxx')
  7. if (this.tabname !== "原始数据") {
  8. return;
  9. }
  10. // if (this.orgchart) {
  11. // this.orgchart.dispose()
  12. // }
  13. var chartDom = document.getElementById("orgChart");
  14. var myChart = echarts.init(chartDom);
  15. const option = {
  16. title: {
  17. left: "center",
  18. text: "原始数据",
  19. },
  20. tooltip: {
  21. trigger: "axis",
  22. axisPointer: {
  23. type: "shadow",
  24. },
  25. },
  26. grid: {
  27. bottom: 90,
  28. },
  29. dataZoom: [{
  30. type: 'inside',//图表下方的伸缩条
  31. show: true, //是否显示
  32. realtime: true, //拖动时,是否实时更新系列的视图
  33. start: this.start, //伸缩条开始位置(1-100),可以随时更改
  34. end: this.end, //伸缩条结束位置(1-100),可以随时更改
  35. },
  36. {
  37. type: 'slider',//图表下方的伸缩条
  38. show: true, //是否显示
  39. realtime: true, //拖动时,是否实时更新系列的视图
  40. start: this.start, //伸缩条开始位置(1-100),可以随时更改
  41. end: this.end, //伸缩条结束位置(1-100),可以随时更改
  42. }
  43.  
  44. ],
  45. xAxis: {
  46. data: this.oscillographX,
  47. silent: false,
  48. splitLine: {
  49. show: false,
  50. },
  51. splitArea: {
  52. show: false,
  53. },
  54. },
  55. yAxis: {
  56. },
  57. series: [
  58. {
  59. // seriesIndex: 9,
  60. type: "line",
  61. data: this.oscillographY,
  62. large: true,
  63. },
  64. ],
  65. };
  66. console.log(myChart.appendData)
  67. myChart.setOption(option, true);
  68. // myChart.appendData({
  69. // seriesIndex: 0,
  70. // data: this.oscillographY
  71. // })
  72. myChart.on('datazoom', function (params) {
  73. // let xAxis = myChart.getModel().option.xAxis[1];//获取axis
  74. console.log(params.batch[0].end, params.batch[0].start, 'xAxis')
  75. that.start = params.batch[0].start;
  76. that.end = params.batch[0].end;
  77.  
  78. });//记录datazoom的滚动距离
  79. this.orgchart = myChart;
  80. this.isStart = false;
  81. return;
  82. },

  绘图中唯一需要做的就是记录datazoom的滚动进度拿到start和end重绘之后进行赋值。

  总结一下:处理的思路就行以一万条数据为一次不断进行轮询,将数据不断的拼接,然后重新绘图。为什么不用echarts提供的appendData()方法呢?因为根本不支持。

原文链接:https://www.cnblogs.com/SadicZhou/p/17191138.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号