能自己做头像的网站,影视logo设计制作器,广西建设局网站首页,wordpress多用户商城系统最近接到个任务#xff0c;需要用vue3实现动态折线图。之前没有用过#xff0c;所以一路坎坷#xff0c;现在记录一下#xff0c;以后也好回忆一下。
之前不清楚echart的绘制方式#xff0c;以为是在第一秒的基础上绘制第二秒#xff0c;后面实验过后#xff0c;发现并…最近接到个任务需要用vue3实现动态折线图。之前没有用过所以一路坎坷现在记录一下以后也好回忆一下。
之前不清楚echart的绘制方式以为是在第一秒的基础上绘制第二秒后面实验过后发现并不是它是每秒都重新绘制整张图。比如现在data里只有一个数据那他就是一个点过一秒之后data里新增一个数据那么就有两个点一条线段依次类推。
话说回来怎么实现动态的折线图回想视频的原理也就是一帧帧的图片快速切换欺骗人眼产生动态的效果。所以折线图也是如此需要设定一个重要的maxLength当data里的数据长度到达这个maxLength使用shift函数去掉data里的第一个数据新的data数组和旧的data数组不同这样两个画面绘制切换就形成了动态的效果。
好了现在有了基本理论该干活了。任务是生成一段折线图如图所示
t0是当前时刻点左边实线是历史数据右侧数据是预测数据预测数据根据当前时刻点进行变化。但是echart没办法实现一个数据前面实线后面虚线只能分成两个数据来拼接假设现在只需要一个静态的画面那么可以这样实现建立一个数组data[历史数据预测数据]这样的形式划分然后分别绘制不同的线段。但是现在需要动态展示。。。 折腾了许久有了第一版的设计设计历史数据只显示在x轴的2/3预测数据全部显示那么超出的预测数据部分就好像是对历史数据的一种预测效果如图 对面在看了这种效果之后觉得还可以。我也就草草实现没管细节了。结果过了几天告诉我增加需求要求可以显示距离报警时间还有多久以及报警之后还有多久报警解除。这个逻辑上是好加的很简单。按照这样的思路 第一如果dataPoint小于outlier且predictions数组里的值都小于outlier的时候显示“状态正常”第二如果dataPoint小于outlier但是predictions数组里的值有值大于等于outlier的时候取第一个满足这个条件的值的索引x显示“距离实际报警还有x分钟”第三如果dataPoint大于等于outlier且predictions数组里的值都大于等于outlier的时候显示“已报警未来持续一段时间”第四如果dataPoint大于等于outlier但是predictions数组里的值有值小于outlier的时候取第一个满足这个条件的值的索引x显示“已报警距离警报解除还有x分钟” dataPoint和predictions都是在updateData中定义变化的。 dataPoint表示实时值outlier表示阈值predictions表示实时值对应的预测数据数组。 实战显示折线图真实情况和对应标题总是对不齐说明这两条线有大问题。之前只是大概满足这个形式这回需要精确到点所以暴露问题了。 问题1历史数据每秒增加1个点预测数据每秒增加15个点大于1个点 问题2根据echart的绘制机制二者动起来的方式都是先到达设定的最大长度且刚开始都是从最左边开始绘制所以如果按照一般形式二者根本对不齐。 这里开始尝试很多解决办法首先是预测数据的存储方式。比如现在是
第一秒历史数据是a预测数据是123那么预测队列为123
第二秒历史数据是b预测数据是456那么预测队列为1456
第三秒历史数据是c预测数据是789那么预测队列为14789
以此类推对应算法
保留原预测数据的第一个值加上新的预测数据if (currentState.currentResponse null) {// 第一次接收数据currentState.currentResponse response;allPredictedData.value[extractedName] [...response];} else {// 将前一次的response第一个值添加到历史currentState.prevFirsts.push(currentState.currentResponse[0]);// 更新当前响应currentState.currentResponse response;// 合并历史数据和新数据allPredictedData.value[extractedName] [...currentState.prevFirsts,...currentState.currentResponse];}由于数据预测的折线图是子组件所以传值也是个问题。之前值都是存在子组件的但是这个样子和父组件失去同步因为父组件有个实时值显示模拟真实情况传感器的数据。如果分开的话父组件的值都走完了点开数据预测界面发现从第一秒开始那么就露馅了。由于父组件不是我写的所以看起来也是脑袋大。 可算改完了这回实时值和预测值都由父组件提供子组件只负责数据的显示。蛋疼的是数据预测是向服务器请求的所以其实实时值和对应的预测数据如果不加处理无法直接对其故将实时值的时间戳和对应的预测数据保存子组件通过监测道名称和时间戳获取对应数据。
const currentTimestamp item.data[currentIndex.value]?.timestamp;allPredictedData.value[extractedName].push({timestamp: currentTimestamp,prediction: response
});这么尝试多次后一两天把。。发现问题仍然无法解决一度怀疑是不是echart的问题还是什么玄学。后面静下心来想想在纸上debug了一下理清逻辑之后发现问题所在。设计出来了最终版 报警时间预测不准的原因是因为两个问题1.二者起始没对齐 2.每秒增加的点数不同。
所以想到了使用填充的方式来使二者在开始对齐右边是历史数据的方式。
第一步获取监测道的全部数据模拟传感器的实时数据所以是有全部数据
第二步打开折线图的时候获取当前点的dataPoint
2.1 结合data从dataPoint向前进行判断有多个点x
2.2填充null形式为[null,x,dataPoint]共20个点;这三步便生成了初始的20个点后面更新的步骤为
2.3获取新的dataPoint加入初始数组初始数组.shift()
左边则是预测数据
第一步初始化和历史数据相同到2.2生成了一个[null,x,dataPoint]初始历史数据数组此时加入当前点的预测数据生成新的数组[初始历史数据数组实时点对应的预测数据]这就是一个初始预测数据数组 第二步初始历史数组.shift(),追加上一个点对应预测数据的第一个点生成第二个历史数据数组
追加实时值的预测数据[第二个历史数据数组实时点对应的预测数据]。
下图为打开折线图的示意图