首页IT科技echarts读取csv数据(JavaScript获取echart曲线上任意点位的值详解)

echarts读取csv数据(JavaScript获取echart曲线上任意点位的值详解)

时间2025-09-16 00:42:28分类IT科技浏览8868
导读:需求背景 智慧农业里有一个很重要的功能是控制温室生长环境,让农作物生长的更好。于是,我们需要在曲线上根据不同农作物设置不同的环境数据。为了方便用户修改这些数据,我们需要支持用户在曲线上进行拖拽,并且拖拽后还需要把拖拽后的关键点位返回给后端。后面温度传感器收到温度数据后,会发给后端和前端。两端都需要判断传过来的温度...

需求背景

智慧农业里有一个很重要的功能是控制温室生长环境                 ,让农作物生长的更好                 。于是                           ,我们需要在曲线上根据不同农作物设置不同的环境数据                           。为了方便用户修改这些数据         ,我们需要支持用户在曲线上进行拖拽        ,并且拖拽后还需要把拖拽后的关键点位返回给后端         。后面温度传感器收到温度数据后                           ,会发给后端和前端        。两端都需要判断传过来的温度是否在曲线之间                           。如果超出或者下沉需要触发相应的事件                  。

需求调研

本来以为这个需求很简单                  ,导入echarts        ,设置两条曲线                          ,并支持拖动        。拖动                          。这些都属于echarts开放的功能                  ,但等到要查询某个时间点曲线上的值时,才发现echarts根本就没开放这个功能                          ,查看源码发现他是用贝塞尔算法生成的曲线                           ,好吧,既然你不支持                 ,那就只能自己实现了                  。

后面找了下资料                           ,发现一个贝塞尔的js开源库         ,看了下它的说明                 ,发现有get(t)方法获取到曲线上Y轴的值。参数t表示两个关键点之间x轴值                          。由于我们传入的x轴是时间                           ,所以这个t就是x轴的时间                           。

所以         ,理论上        ,如果两个使用的算法是一致的                           ,那么从曲线上获得的值就应该是一样的。

实现步骤

第一步                  ,安装bezier-js

npm install bezier-js

第二步        ,初始化贝塞尔对象

constructor(input = {points: [20, 30, 40], ts: [0, 60000 * 60 * 24]}) { this.line = null this.keyPoints = []//根据输入input                          ,生成关键的点坐标数组 [ x1坐标,y1坐标                  , x2坐标,y2坐标 ] this.tsStart = 0 this.tsEnd = 0 this.init(input) this.input = input } init(input) { try { if (![input].$has(ts)) input.ts = [0, 60000 * 60 * 24]//如果没有ts时间,默认赋值为1天的时间周期 if (![input].$has(points, ts) || input.points.length < 2 || input.ts.length !== 2) { console.log(【bezier】错误!实例化曲线时参数错误) return//最小2个点 } this.tsStart = Number(input.ts[0]) this.tsEnd = Number(input.ts[1]) let tsLen = this.tsEnd - this.tsStart if (tsLen < 0) { console.log(【bezier】错误!实例化曲线时参数错误,时间长度错误) return } let stepLen = tsLen / (input.points.length - 1) let points = [] let x = input.ts[0] input.points.forEach(y => { points.push({x: x}) points.push({y: y}) x += stepLen }) points.splice(points.length - 2, 2)//删除最后一组坐标(2个元素) points.push({x: input.ts[1]})//再用input的值填充                          ,避免因为平均值导致精度的问题 points.push({y: input.points[input.points.length - 1]}) this.keyPoints = points this.line = new Bezier(points) // points = [ x1坐标,y1坐标                           , x2坐标,y2坐标 ] console.log(生成贝塞尔曲线的数据, this.line, points) } catch (e) { console.log(【bezier】错误!在实例化对象时错误, e) } }

第三步,我们曲线上看到的是时间是“时+分                  ”格式                 ,传入的要转化为时间戳

// 获取指定时间戳的y值数据 // ts横坐标                           ,时间戳 // 输出 {x,y}          ,x就是 ts get(ts = 0) { let duration if (ts <= this.tsStart) { duration = 0 } else if (ts <= this.tsEnd) { duration = ts - this.tsStart } else { duration = this.tsEnd - this.tsStart } let b = duration / (this.tsEnd - this.tsStart) return this.line.get(b) // b取值0~1                 ,小数.0表示曲线第一个点                           ,1表示最后1个点 }

第四步         ,服务端给我们的关键点位可能有几十个        ,如果我通过几十个点生成贝塞尔对象                           ,在通过get值去查询时候                  ,由于它内部的算法        ,除了收尾两个关键点外                          ,其他关键点位根据时间查询出的Y值会有偏差                 。这跟我们在echarts曲线上看到的值并不一样                           。我猜原因在于echarts的平滑曲线并不是由首尾两个点生成的                  ,而是由两个两个关键点生成一段一段平滑曲线组合而成的         。

为了验证我的猜想,我写了个demo                          ,通过6个关键点在echarts上生成了二条曲线                 。同时                           ,我通过bezier-js的get(t)方法获取更多点位,然后放到echars上                 ,看两者的曲线是否重合                           。

事实证明                           ,我的猜想是对的         。两者曲线是重合的        。

echarts 根据六个点生成的曲线

下图是根据两个关键点之间计算多个节点组合成的曲线

所以         ,我们在计算某个时间轴的Y轴时                 ,要先判断查询的X轴时间属于哪两个点之间                           ,然后再用get(t)方法查Y值

/** * 查询曲线上某个时间点曲线上具体的值         ,这里查询的是上限                           。 */ getPointValueByTime() { // 把时间转换成毫秒 let time = this.timeToSec(this.defaultTime) // 判断这个时间在哪两个关键点之间 // 先获取曲线上所有时间点的数组 let preData = [] for (var i = 0; i < upperLimit.length; i++) { let itemTime = this.timeToSec(upperLimit[i][0]) // 如果查询的时间小于当前的item        ,这表示在这个item和上一个item之间                  。则通过这两个item生成贝塞尔对象                           ,然后用get方法查询time值 if (time <= itemTime && i != 0) { // 查询的点就是preData 和item的数组 let pointArray = [] pointArray.push(preData[1]) pointArray.push(upperLimit[i][1]) const bezier = new BezierLine({points: pointArray, ts: [preData[0], itemTime]}) let data = bezier.get(time) console.log(查询到当前时间 + time + 的值为, data) this.searchValueByTime = parseFloat(data.y).toFixed(2) break } else { // 上一个不符合的对象 preData = [itemTime, upperLimit[i][1]] } } },

到此                  ,我们就可以通过任意一个X轴时间来获得对应的Y轴value值了        。当然        ,文章里只是把实现思路讲了                          ,贴出来的代码不是全部                  ,只是供大家理解                          。完整版代码我已经上传到码云,如果有什么bug                          ,大家可以留言告知一下                  。 下载地址:GetEchartsCurveData

以上就是JavaScript获取echart曲线上任意点位的值详解的详细内容                           ,更多关于JavaScript echart曲线任意点位值的资料请关注本站其它相关文章!

声明:本站所有文章,如无特殊说明或标注                 ,均为本站原创发布。任何个人或组织                           ,在未征得本站同意时         ,禁止复制                 、盗用                           、采集         、发布本站内容到任何网站        、书籍等各类媒体平台                          。如若本站内容侵犯了原著者的合法权益                 ,可联系我们进行处理                           。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
伪原创文章什么意思(伪原创文章工具入口) aquarium顶部过滤器安装教程(AquariumDesktop.exe进程危险吗 AquariumDesktop是什么进程)