mock折线图Echarts数据
注意:必须要用reactive,不能用ref,否则数据量很大的时候会报错Maximum call stack size exceeded超出最大调用堆栈大小
import moment from 'moment'
const date = ref(moment().format('YYYY-MM-DD'))
const selectType = ref(3) //1表示时,2表示分,3表示秒
const setInterDelay = {
3: {
time: 1000,
func: (val: string) => moment(val).format('HH:mm:ss'),
name: '每秒',
nowTime: moment().format('YYYY-MM-DD HH:mm:ss'),
format: 'YYYY-MM-DD HH:mm:ss',
},
2: {
time: 60 * 1000,
func: (val: string) => moment(val).format('HH:mm'),
name: '每分',
nowTime: moment().format('YYYY-MM-DD HH:mm'),
format: 'YYYY-MM-DD HH:mm',
},
1: {
time: 60 * 60 * 1000,
func: (val: string) => moment(val).format('HH'),
name: '每时',
nowTime: moment().format('YYYY-MM-DD HH'),
format: 'YYYY-MM-DD HH',
},
}
// 看用哪种格式
const echartData = reactive({
data: [],//格式[{label:'2024-05-20 09:09:09',value:'290.00'},...]
xData: [],//格式['2024-05-20 09:09:09','2024-05-20 09:09:10',...]
yData: [],//格式['290.00','190.00',...]
})
onMounted(() => {
console.log('挂载了')
setInterGetData()
})
onUnmounted(() => {
console.log('卸载了')
window.clearInterval(timer.value)
})
const setInterGetData = () => {
window.clearInterval(timer.value)
loading.value = true
generateData() //初始化数据
if (moment().format('YYYY-MM-DD') === date.value) {
getItervalData() //定时数据
}
}
// 过去时间不轮询
const getItervalData = () => {
timer.value = window.setInterval(() => {
setTimeout(() => {
getPollingData()
}, 0)
}, setInterDelay[selectType.value].time)
}
// 手动mock返回的数据
function generateData() {
//====mock时间begin=====
const { time, func } = setInterDelay[selectType.value]
let currentDay = date.value !== moment().format('YYYY-MM-DD'), //是否是当天时间
startDate = date.value + ' 00:00:00', //开始时间
endDate = currentDay ? date.value + ' 23:59:59' : new Date(), //结束时间
countTimeCha = new Date(startDate).getTime() - new Date(endDate).getTime(), //开始时间和结束时间毫秒差
countDelay = Math.abs(countTimeCha / time).toFixed(), //根据秒分时,确定x轴的时间长度
count = currentDay ? Number(countDelay) : Number(countDelay) - 1 //当天时间取上一秒分时,过去的时间取全部
// count = 86400 //当天时间取上一秒分时,过去的时间取全部
console.log(count, 'count')
//====mock时间end=====
//====mock数据begin=====
let timeDelay = +new Date(startDate)
let baseValue = Math.random() * 1000
let smallBaseValue = 0
function next(idx: number) {
smallBaseValue = idx % 30 === 0 ? Math.random() * 700 : smallBaseValue + Math.random() * 500 - 250
baseValue += Math.random() * 20 - 10
return Math.max(0, Math.round(baseValue + smallBaseValue) + 3000)
}
//====mock数据end=====
const categoryData: any = []
const valueData: any = []
const echartXYData: any = []
for (let i = 0; i < count; i++) {
//===============
categoryData.push(func(timeDelay))
valueData.push(next(i).toFixed(2))
//===============
echartXYData.push({
label: func(timeDelay),
value: next(i).toFixed(2),
})
timeDelay += time
}
//===============
echartData.xData = []
echartData.xData = categoryData
echartData.yData = []
echartData.yData = valueData
//===============
echartData.data = []
echartData.data = echartXYData
}
const getPollingData = async () => {
const { format } = setInterDelay[selectType.value]
const nowTime = moment().format(format)
const paramsData = {
date: nowTime,
timeType: selectType.value,
...props.params,
}
const data: any = {
xData: [nowTime],
yData: [Math.random().toString().slice(2, 6)],
}
echartData.xData = echartData.xData.concat(data.xData)
echartData.yData = echartData.yData.concat(data.yData)
loading.value = false
}
大数据时的渲染优化
- dataZoom
dataZoom: [
{
type: 'inside', //内置型数据区域缩放组件
show: true, //是否显示
realtime: true, //拖动时,是否实时更新系列的视图
start: 90,//伸缩条开始位置(1-100),可以随时更改
end: 100,//伸缩条结束位置(1-100),可以随时更改
},
{
type: 'slider', //滑动条型数据区域缩放组件
show: true, //是否显示
realtime: true, //拖动时,是否实时更新系列的视图
start: 90,//伸缩条开始位置(1-100),可以随时更改
end: 100,//伸缩条结束位置(1-100),可以随时更改
},
],
const options = ref(props.option)
const draw = () => {
if (chartInstance.value) {
chartInstance.value.setOption(props.option, { notMerge: true })
if (props.dataZoom)
chartInstance.value.on('datazoom', (params: any) => {
let start = 0,
end = 0
start = params.batch ? params.batch[0].start : params.start
end = params.batch ? params.batch[0].end : params.end
options.value.dataZoom[0].start = start
options.value.dataZoom[0].end = end
options.value.dataZoom[1].start = start
options.value.dataZoom[1].end = end
})
}
}
watch(props, () => {
options.value = props.option
draw()
})
series: {
data: [],
type: 'line',
sampling: 'average', //降采样渲染
...
}
- 轮询获取数据
getListWaveformDat(count) {
this.loading = true;//加载loading动画
//获取波形图数据
getListWaveformDat({
deviceId: this.queryPointParams.deviceId,
diId: this.diId,
reportedOn: this.orgTime,
keyName: this.dataAxis,
num: this.pageNum,
size: 10000,
count: count ? count : '',
}).then((res) => {
if (res.length > 0) {
this.noData = false//是否加载缺省值图片
console.log(this.orgchart)
if (this.orgchart) {
this.orgchart.dispose();
}
this.oscillograph = res;
let x = [];
for (let i = 0; i < this.oscillograph.length; i++) {
x[i] = this.oscillograph[i].count;
}//处理X轴数据
let y = [];
for (let i = 0; i < this.oscillograph.length; i++) {
y[this.oscillograph[i].count * 1 - 1] = this.oscillograph[i].value * 1
}
for (let i = 0; i < this.oscillographY.length; i++) {
if (this.oscillographY[i] == undefined) {
if (y[i]) {
this.oscillographY[i] = y[i]
}
}
}//处理Y轴数据
console.log(this.oscillographY)
this.pageNum = this.pageNum + 1;//轮询次数加1
this.$nextTick(() => {
this.orgDraw();//绘制图表
})
this.loading = false;//关闭加载loading
this.getListWaveformDat(x[x.length - 1])//继续轮询
}
else {
//如果加载的数据为空
this.loading = false;
console.log(this.orgchart)
if (this.pageNum == 1) {
//如果第一次轮询就为空,加载缺省图片
this.noData = true;
if (this.orgchart) {
this.orgchart.dispose();//清除上一次加载的图表
}
this.pageNum = 1;//请求完所有数据之后初始化一下
return
}
});
}
出现Maximum call stack size exceeded超出最大调用堆栈大小
原因:用的ref,5000+数据就会报错了
解决:用reactive代替ref
参考文献: