vue使用echarts實現(xiàn)動態(tài)數(shù)據(jù)的示例詳解
echarts 中有一個圖形叫動態(tài)數(shù)據(jù)+時間坐標軸,這個一般用于我們圖形數(shù)據(jù)較多,或需要左側平移動態(tài)展示折線圖或者其他圖形的情況,但是使用這個的時候,一般數(shù)據(jù)沒問題,如果碰上我這種同一個x軸上,有兩個值的情況就比較麻煩。 下面分享一下。
官方案例: echarts.apache.org/examples/zh/editor.html

場景
我們的場景就是同樣有一批數(shù)據(jù),需要不斷的左移顯示, x 軸顯示站點, y軸顯示我這個站的壓力值, 正常來說我一個站有兩個壓力值, 但是經(jīng)常會有這兩個值相同的情況,相同的時候,就顯示一個點, 不相同的時候,就在同一個 x 軸上顯示兩個點。 官方給我們的代碼 是使用 定時器輪詢,來更新數(shù)據(jù)

但是官方的代碼不是循環(huán)的,他這個更新你看到了 shift 刪除了第一項,這個第一項就沒了, 而我的需求是像輪播圖一樣, 要循環(huán)數(shù)據(jù), 也就是刪除的第一項要插回到數(shù)據(jù)的最后一條去。
數(shù)據(jù)
我覺得這里應該先給大家展示數(shù)據(jù), 然后根據(jù)數(shù)據(jù)再展開就方便理解了。
allData: [
{
showx: '節(jié)點1',
showy: 7.40019,
value: ['節(jié)點1', 7.40019],
source: {
stationName: '節(jié)點1',
pressureIn: 7.40019,
pressureOut: 7.40019,
same: true,
},
},
{
showx: '節(jié)點2',
showy: 4.673716,
value: ['節(jié)點2', 4.673716],
source: {
stationName: '節(jié)點2',
pressureIn: 4.673716,
pressureOut: 7.477946,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點2',
showy: 7.477946,
value: ['節(jié)點2', 7.477946],
source: {
stationName: '節(jié)點2',
pressureIn: 4.673716,
pressureOut: 7.477946,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點3',
showy: 6.699683,
value: ['節(jié)點3', 6.699683],
source: {
stationName: '節(jié)點3',
pressureIn: 6.699683,
pressureOut: 7.928933,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點3',
showy: 7.928933,
value: ['節(jié)點3', 7.928933],
source: {
stationName: '節(jié)點3',
pressureIn: 6.699683,
pressureOut: 7.928933,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點4',
showy: 10,
value: ['節(jié)點4', 10],
source: {
stationName: '節(jié)點4',
pressureIn: 10,
pressureOut: 10,
same: true,
},
},
{
showx: '節(jié)點5',
showy: 7.514252,
value: ['節(jié)點5', 7.514252],
source: {
stationName: '節(jié)點5',
pressureIn: 7.514252,
pressureOut: 7.514252,
same: true,
},
},
{
showx: '節(jié)點8',
showy: 8.152734,
value: ['節(jié)點8', 8.152734],
source: {
stationName: '節(jié)點8',
pressureIn: 8.152734,
pressureOut: 8.152734,
same: true,
},
},
{
showx: '節(jié)點9',
showy: 7.925224,
value: ['節(jié)點9', 7.925224],
source: {
stationName: '節(jié)點9',
pressureIn: 7.925224,
pressureOut: 8.410707,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點9',
showy: 8.410707,
value: ['節(jié)點9', 8.410707],
source: {
stationName: '節(jié)點9',
pressureIn: 7.925224,
pressureOut: 8.410707,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點11',
showy: 7.309628,
value: ['節(jié)點11', 7.309628],
source: {
stationName: '節(jié)點11',
pressureIn: 7.309628,
pressureOut: 7.309628,
same: true,
},
},
]
上面就是我的數(shù)據(jù), 實際上這個數(shù)據(jù)已經(jīng)經(jīng)過我的改造了, 那么正常來講 官方示例當中,是不會出現(xiàn)我這里面比如節(jié)點3這種 重復節(jié)點的情況, 這時候往左側平移是一點問題沒有的, 但如果我這個里面有重復的節(jié)點, 而我使用正常左移1個,然后再把左移這個插回到數(shù)組最后一個會怎么樣? 會這樣:

大家可以看到, 當我滾動到有兩個重復節(jié)點的時候,左側會出現(xiàn)一個空位, 而我的需求是需要再 x 軸上顯示 一個節(jié)點,兩個值, 這兩個值在一條x軸上, 方便看到變化。 出現(xiàn)這個問題的原因就是我移動了一個節(jié)點, 但這兩個節(jié)點實際上是顯示在一條x軸上的, 移走了一個, 只剩下另一個,就不能夠正常顯示。 所以我移動節(jié)點的時候,應該判斷左移出去的節(jié)點是否是重復節(jié)點,如果是,應該兩個都刪除,然后插入到我數(shù)組的后面。
這里還有一個注意點,就是我們需要使用兩個數(shù)據(jù)來管理狀態(tài),因為不像官方的 demo,我這里要對數(shù)組刪除以后,還要插入,需要找到指定的數(shù)據(jù),所以一個數(shù)組存儲不變狀態(tài),我們從這里拿指定的數(shù)據(jù),另一個數(shù)組用來展示,這個數(shù)組可以刪除,更改。同時需要一個 index, 來記錄我們每次拿取數(shù)據(jù)的指針。
最終效果

代碼
以下是我的完整代碼, 可以直接使用, 看到效果, 關鍵邏輯也有注釋, 然后有疑問的地方,大家可以留言,一起討論~ pipelinePressureData 這里面的邏輯大家可以不用看,這是我用來轉換數(shù)據(jù)用的。
<template>
<div>
<div id="demo-main"></div>
</div>
</template>
<script>
import * as echarts from 'echarts';
export default {
props:{
pipelinePressureData:{
type: Array,
default: () => []
}
},
name: 'PipelinePressureChart',
data(){
return {
showData:[ ],
lastIndex: 0,
timeID: 0,
allData: [
{
showx: '節(jié)點1',
showy: 7.40019,
value: ['節(jié)點1', 7.40019],
source: {
stationName: '節(jié)點1',
pressureIn: 7.40019,
pressureOut: 7.40019,
same: true,
},
},
{
showx: '節(jié)點2',
showy: 4.673716,
value: ['節(jié)點2', 4.673716],
source: {
stationName: '節(jié)點2',
pressureIn: 4.673716,
pressureOut: 7.477946,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點2',
showy: 7.477946,
value: ['節(jié)點2', 7.477946],
source: {
stationName: '節(jié)點2',
pressureIn: 4.673716,
pressureOut: 7.477946,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點3',
showy: 6.699683,
value: ['節(jié)點3', 6.699683],
source: {
stationName: '節(jié)點3',
pressureIn: 6.699683,
pressureOut: 7.928933,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點3',
showy: 7.928933,
value: ['節(jié)點3', 7.928933],
source: {
stationName: '節(jié)點3',
pressureIn: 6.699683,
pressureOut: 7.928933,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點4',
showy: 10,
value: ['節(jié)點4', 10],
source: {
stationName: '節(jié)點4',
pressureIn: 10,
pressureOut: 10,
same: true,
},
},
{
showx: '節(jié)點5',
showy: 7.514252,
value: ['節(jié)點5', 7.514252],
source: {
stationName: '節(jié)點5',
pressureIn: 7.514252,
pressureOut: 7.514252,
same: true,
},
},
{
showx: '節(jié)點8',
showy: 8.152734,
value: ['節(jié)點8', 8.152734],
source: {
stationName: '節(jié)點8',
pressureIn: 8.152734,
pressureOut: 8.152734,
same: true,
},
},
{
showx: '節(jié)點9',
showy: 7.925224,
value: ['節(jié)點9', 7.925224],
source: {
stationName: '節(jié)點9',
pressureIn: 7.925224,
pressureOut: 8.410707,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點9',
showy: 8.410707,
value: ['節(jié)點9', 8.410707],
source: {
stationName: '節(jié)點9',
pressureIn: 7.925224,
pressureOut: 8.410707,
same: false,
type: 'pressureOut',
},
},
{
showx: '節(jié)點11',
showy: 7.309628,
value: ['節(jié)點11', 7.309628],
source: {
stationName: '節(jié)點11',
pressureIn: 7.309628,
pressureOut: 7.309628,
same: true,
},
},
]
}
},
mounted(){
},
beforeDestroy(){
clearInterval(this.timeID)
},
watch:{
pipelinePressureData:{
deep: true,
immediate: true,
handler(val){
if(val?.length === 0 ) return
const res = val.reduce((prev,item)=>{
const { pressureIn, pressureOut, stationName} = item
if(pressureIn === pressureOut){
prev.push({
showx: stationName,
showy: pressureIn,
value: [stationName,pressureIn],
source: Object.assign(item, { same: true })
})
}else{
prev.push({
showx: stationName,
showy: pressureIn,
value: [stationName,pressureIn],
source: Object.assign(item, { same: false, type: 'pressureIn' })
})
prev.push({
showx: stationName,
showy: pressureOut,
value: [stationName,pressureOut],
source: Object.assign(item, { same: false, type: 'pressureOut' })
})
}
return prev
},[])
// this.allData = res
console.log('res',res);
this.$nextTick(()=>{
this.init()
})
}
}
},
methods: {
init(){
var chartDom = document.getElementById('demo-main');
var myChart = echarts.init(chartDom, 'dark', {
useDirtyRect: true
});
var option;
const allIndxe = this.allData.length
const bool = allIndxe > 6
if(bool){
this.showData = this.allData.slice(0,6)
this.lastIndex = 5
}else{
this.showData = this.allData
}
option = {
grid: {
left: '2%', // 如果需要,可以調(diào)整左邊距
right: '1%', // 如果需要,可以調(diào)整右邊距
bottom: '3%', // 增加底部邊距以容納更多的 X 軸標簽
containLabel: true // 確保標簽被容納在圖表區(qū)域內(nèi)
},
title: {
text: '測試數(shù)據(jù)'
},
tooltip: {
trigger: 'axis',
formatter: function (params) {
params = params[0];
const { data: { source } } = params
const { same, stationName, type, pressureIn, pressureOut } = source
return `<div>場站${stationName}</div><div>進壓力${pressureIn}</div><div>出壓力${pressureOut}</div>`
},
axisPointer: {
animation: false
}
},
xAxis: {
type: 'category',
name: '名稱',
splitLine: {
show: false
},
axisTick: {
alignWithLabel: true
},
axisLabel: {
formatter: (value) => {
return value === "" ? '\n' : value
}
},
axisLabel: {
interval: 0, // 強制顯示所有標簽
rotate: 45, // 如果需要,可以設置標簽旋轉角度以避免重疊
textStyle: {
fontSize: 10 // 如果需要,可以適當調(diào)整字體大小
}
}
},
yAxis: {
type: 'value',
boundaryGap: [0, '100%'],
splitLine: {
show: false
}
},
series: [
{
name: 'Fake Data',
type: 'line',
showSymbol: false,
data: this.showData
}
]
};
if(bool){
this.timeID = setInterval(()=>{
this.lastIndex++
if(this.lastIndex === allIndxe){
this.lastIndex = 0
}
this.showData.shift()
this.showData.push(this.allData[this.lastIndex])
if(this.showData[0].showx === this.showData[1].showx){
this.lastIndex++
if(this.lastIndex === allIndxe){
this.lastIndex = 0
}
this.showData.shift()
this.showData.push(this.allData[this.lastIndex])
}
myChart.setOption({
xAxis: {
// data: this.showData.map(item=>item.showx)
data: this.showData.reduce((prev, item, index, arr) => {
const { showx } = item;
// 排除空字符串,只添加非空的標簽
if (showx !== '') {
// 判斷當前標簽與下一個標簽是否相同,相同則不添加
if (showx !== arr[index + 1]?.showx) {
prev.push(showx);
}
}
return prev;
}, []),
},
series: [
{
data: this.showData
}
]
})
},2000)
}
option && myChart.setOption(option);
}
}
}
</script>
<style lang="scss" scoped>
#demo-main{
border: 1px solid #333;
width: 500px;
height: 300px
}
</style>
以上就是vue使用echarts實現(xiàn)動態(tài)數(shù)據(jù)的示例詳解的詳細內(nèi)容,更多關于vue echarts動態(tài)數(shù)據(jù)的資料請關注腳本之家其它相關文章!
相關文章
基于uniapp+vue3自定義增強版table表格組件「兼容H5+小程序+App端」
uv3-table:一款基于uniapp+vue3跨端自定義手機端增強版表格組件,支持固定表頭/列、邊框、斑馬紋、單選/多選,自定義表頭/表體插槽、左右固定列陰影高亮顯示,支持編譯兼容H5+小程序端+App端,H5+小程序+App端,多端運行一致2024-05-05
Vue項目中大文件切片上傳實現(xiàn)秒傳與斷點續(xù)傳的詳細實現(xiàn)過程
這篇文章主要給大家介紹了關于Vue項目中大文件切片上傳實現(xiàn)秒傳與斷點續(xù)傳的詳細實現(xiàn)過程, 在開發(fā)中,如果上傳的文件過大,可以考慮分片上傳,分片就是說將文件拆分來進行上傳,將各個文件的切片傳遞給后臺,然后后臺再進行合并,需要的朋友可以參考下2023-08-08
Vue結合Openlayers使用Overlay添加Popup彈窗實現(xiàn)
本文主要介紹了Vue結合Openlayers使用Overlay添加Popup彈窗實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05
vue+tsc+noEmit導致打包報TS類型錯誤問題及解決方法
當我們新建vue3項目,package.json文件會自動給我添加一些配置選項,這寫選項基本沒有問題,但是在實際操作過程中,當項目越來越復雜就會出現(xiàn)問題,本文給大家分享vue+tsc+noEmit導致打包報TS類型錯誤問題及解決方法,感興趣的朋友一起看看吧2023-10-10
vue框架和react框架的區(qū)別以及各自的應用場景使用
這篇文章主要介紹了vue框架和react框架的區(qū)別以及各自的應用場景使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
Vue.js中自定義Markdown插件實現(xiàn)References解析(推薦)
本文主要寫的是,如何編寫一個插件來解析<references>標簽,并將其轉換為HTML,這種方法可以應用于其他自定義標簽和功能,為Vue.js應用程序中的Markdown渲染提供了極大的靈活性,感興趣的朋友跟隨小編一起看看吧2024-07-07

