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

JavaScript獲取echart曲線上任意點(diǎn)位的值詳解

 更新時(shí)間:2022年09月30日 10:04:53   作者:石云升  
這篇文章主要為大家介紹了JavaScript獲取echart曲線上任意點(diǎn)位的值詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

需求背景

智慧農(nóng)業(yè)里有一個(gè)很重要的功能是控制溫室生長(zhǎng)環(huán)境,讓農(nóng)作物生長(zhǎng)的更好。于是,我們需要在曲線上根據(jù)不同農(nóng)作物設(shè)置不同的環(huán)境數(shù)據(jù)。為了方便用戶修改這些數(shù)據(jù),我們需要支持用戶在曲線上進(jìn)行拖拽,并且拖拽后還需要把拖拽后的關(guān)鍵點(diǎn)位返回給后端。后面溫度傳感器收到溫度數(shù)據(jù)后,會(huì)發(fā)給后端和前端。兩端都需要判斷傳過(guò)來(lái)的溫度是否在曲線之間。如果超出或者下沉需要觸發(fā)相應(yīng)的事件。

需求調(diào)研

本來(lái)以為這個(gè)需求很簡(jiǎn)單,導(dǎo)入echarts,設(shè)置兩條曲線,并支持拖動(dòng)。拖動(dòng)。這些都屬于echarts開(kāi)放的功能,但等到要查詢某個(gè)時(shí)間點(diǎn)曲線上的值時(shí),才發(fā)現(xiàn)echarts根本就沒(méi)開(kāi)放這個(gè)功能,查看源碼發(fā)現(xiàn)他是用貝塞爾算法生成的曲線,好吧,既然你不支持,那就只能自己實(shí)現(xiàn)了。

后面找了下資料,發(fā)現(xiàn)一個(gè)貝塞爾的js開(kāi)源庫(kù),看了下它的說(shuō)明,發(fā)現(xiàn)有g(shù)et(t)方法獲取到曲線上Y軸的值。參數(shù)t表示兩個(gè)關(guān)鍵點(diǎn)之間x軸值。由于我們傳入的x軸是時(shí)間,所以這個(gè)t就是x軸的時(shí)間。

所以,理論上,如果兩個(gè)使用的算法是一致的,那么從曲線上獲得的值就應(yīng)該是一樣的。

實(shí)現(xiàn)步驟

第一步,安裝bezier-js

npm install bezier-js

第二步,初始化貝塞爾對(duì)象

constructor(input = {points: [20, 30, 40], ts: [0, 60000 * 60 * 24]}) {
    this.line = null
    this.keyPoints = []//根據(jù)輸入input,生成關(guān)鍵的點(diǎn)坐標(biāo)數(shù)組    [   x1坐標(biāo),y1坐標(biāo),  x2坐標(biāo),y2坐標(biāo)     ]
    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]//如果沒(méi)有ts時(shí)間,默認(rèn)賦值為1天的時(shí)間周期
        if (![input].$has('points', 'ts') || input.points.length < 2 || input.ts.length !== 2) {
            console.log('【bezier】錯(cuò)誤!實(shí)例化曲線時(shí)參數(shù)錯(cuò)誤')
            return//最小2個(gè)點(diǎn)
        }
        this.tsStart = Number(input.ts[0])
        this.tsEnd = Number(input.ts[1])
        let tsLen = this.tsEnd - this.tsStart
        if (tsLen < 0) {
            console.log('【bezier】錯(cuò)誤!實(shí)例化曲線時(shí)參數(shù)錯(cuò)誤,時(shí)間長(zhǎng)度錯(cuò)誤')
            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)//刪除最后一組坐標(biāo)(2個(gè)元素)
        points.push({x: input.ts[1]})//再用input的值填充,避免因?yàn)槠骄祵?dǎo)致精度的問(wèn)題
        points.push({y: input.points[input.points.length - 1]})
        this.keyPoints = points
        this.line = new Bezier(points)  // points =  [   x1坐標(biāo),y1坐標(biāo),  x2坐標(biāo),y2坐標(biāo)     ]
        console.log('生成貝塞爾曲線的數(shù)據(jù)', this.line, points)
    } catch (e) {
        console.log('【bezier】錯(cuò)誤!在實(shí)例化對(duì)象時(shí)錯(cuò)誤', e)
    }
}

第三步,我們曲線上看到的是時(shí)間是“時(shí)+分”格式,傳入的要轉(zhuǎn)化為時(shí)間戳

// 獲取指定時(shí)間戳的y值數(shù)據(jù)
// ts橫坐標(biāo),時(shí)間戳
// 輸出 {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,小數(shù).0表示曲線第一個(gè)點(diǎn),1表示最后1個(gè)點(diǎn)
}

第四步,服務(wù)端給我們的關(guān)鍵點(diǎn)位可能有幾十個(gè),如果我通過(guò)幾十個(gè)點(diǎn)生成貝塞爾對(duì)象,在通過(guò)get值去查詢時(shí)候,由于它內(nèi)部的算法,除了收尾兩個(gè)關(guān)鍵點(diǎn)外,其他關(guān)鍵點(diǎn)位根據(jù)時(shí)間查詢出的Y值會(huì)有偏差。這跟我們?cè)趀charts曲線上看到的值并不一樣。我猜原因在于echarts的平滑曲線并不是由首尾兩個(gè)點(diǎn)生成的,而是由兩個(gè)兩個(gè)關(guān)鍵點(diǎn)生成一段一段平滑曲線組合而成的。

為了驗(yàn)證我的猜想,我寫(xiě)了個(gè)demo,通過(guò)6個(gè)關(guān)鍵點(diǎn)在echarts上生成了二條曲線。同時(shí),我通過(guò)bezier-js的get(t)方法獲取更多點(diǎn)位,然后放到echars上,看兩者的曲線是否重合。

事實(shí)證明,我的猜想是對(duì)的。兩者曲線是重合的。

echarts 根據(jù)六個(gè)點(diǎn)生成的曲線

下圖是根據(jù)兩個(gè)關(guān)鍵點(diǎn)之間計(jì)算多個(gè)節(jié)點(diǎn)組合成的曲線

所以,我們?cè)谟?jì)算某個(gè)時(shí)間軸的Y軸時(shí),要先判斷查詢的X軸時(shí)間屬于哪兩個(gè)點(diǎn)之間,然后再用get(t)方法查Y值

/**
 * 查詢曲線上某個(gè)時(shí)間點(diǎn)曲線上具體的值,這里查詢的是上限。
 */
getPointValueByTime() {
    // 把時(shí)間轉(zhuǎn)換成毫秒
    let time = this.timeToSec(this.defaultTime)
    // 判斷這個(gè)時(shí)間在哪兩個(gè)關(guān)鍵點(diǎn)之間
    // 先獲取曲線上所有時(shí)間點(diǎn)的數(shù)組
    let preData = []
    for (var i = 0; i < upperLimit.length; i++) {
        let itemTime = this.timeToSec(upperLimit[i][0])
        // 如果查詢的時(shí)間小于當(dāng)前的item,這表示在這個(gè)item和上一個(gè)item之間。則通過(guò)這兩個(gè)item生成貝塞爾對(duì)象,然后用get方法查詢time值
        if (time <= itemTime && i != 0) {
            // 查詢的點(diǎn)就是preData 和item的數(shù)組
            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('查詢到當(dāng)前時(shí)間' + time + '的值為', data)
            this.searchValueByTime = parseFloat(data.y).toFixed(2)
            break
        } else {
            // 上一個(gè)不符合的對(duì)象
            preData = [itemTime, upperLimit[i][1]]
        }
    }
},

到此,我們就可以通過(guò)任意一個(gè)X軸時(shí)間來(lái)獲得對(duì)應(yīng)的Y軸value值了。當(dāng)然,文章里只是把實(shí)現(xiàn)思路講了,貼出來(lái)的代碼不是全部,只是供大家理解。完整版代碼我已經(jīng)上傳到碼云,如果有什么bug,大家可以留言告知一下。 下載地址:GetEchartsCurveData

以上就是JavaScript獲取echart曲線上任意點(diǎn)位的值詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript echart曲線任意點(diǎn)位值的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue解決跨域問(wèn)題(推薦)

    vue解決跨域問(wèn)題(推薦)

    這篇文章主要介紹了vue解決跨域問(wèn)題,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • vue中v-model的應(yīng)用及使用詳解

    vue中v-model的應(yīng)用及使用詳解

    v-model用于表單數(shù)據(jù)的雙向綁定,其實(shí)它就是一個(gè)語(yǔ)法糖。這篇文章主要介紹了vue中v-model的應(yīng)用,需要的朋友可以參考下
    2018-06-06
  • 基于vue的換膚功能的示例代碼

    基于vue的換膚功能的示例代碼

    本篇文章主要介紹了基于vue的換膚功能的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • vue-pdf打包后無(wú)法預(yù)覽問(wèn)題及修復(fù)方式

    vue-pdf打包后無(wú)法預(yù)覽問(wèn)題及修復(fù)方式

    這篇文章主要介紹了vue-pdf打包后無(wú)法預(yù)覽問(wèn)題及修復(fù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue loadmore 組件滑動(dòng)加載更多源碼解析

    vue loadmore 組件滑動(dòng)加載更多源碼解析

    這篇文章主要介紹了vue loadmore 組件滑動(dòng)加載更多源碼解析,需要的朋友可以參考下
    2017-07-07
  • vue使用pinia實(shí)現(xiàn)全局無(wú)縫通信

    vue使用pinia實(shí)現(xiàn)全局無(wú)縫通信

    這篇文章主要為大家詳細(xì)介紹了vue如何使用pinia實(shí)現(xiàn)全局無(wú)縫通信,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2023-11-11
  • vue.js中methods watch和computed的區(qū)別示例詳解

    vue.js中methods watch和computed的區(qū)別示例詳解

    methods,watch和computed都是以函數(shù)為基礎(chǔ)的,但各自卻都不同,這篇文章主要給大家介紹了關(guān)于vue.js中methods watch和computed區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • Vue路由history模式解決404問(wèn)題的幾種方法

    Vue路由history模式解決404問(wèn)題的幾種方法

    這篇文章主要介紹了Vue路由history模式解決404問(wèn)題的幾種方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • 淺談Vue.js中的v-on(事件處理)

    淺談Vue.js中的v-on(事件處理)

    本篇文章主要介紹了Vue.js中的v-on(事件處理),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • 使用vant-picker實(shí)現(xiàn)自定義內(nèi)容,根據(jù)內(nèi)容添加圖標(biāo)

    使用vant-picker實(shí)現(xiàn)自定義內(nèi)容,根據(jù)內(nèi)容添加圖標(biāo)

    這篇文章主要介紹了使用vant-picker實(shí)現(xiàn)自定義內(nèi)容,根據(jù)內(nèi)容添加圖標(biāo),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評(píng)論