需求:
当数据跨度不满30分钟时,数据曲线逐渐向右增加,当数据时间跨度超过30分钟后,曲线在近30分钟的时间窗口进行平滑移动过度。
实现思路:
- 存储近30分钟的曲线数据,为了保证数据更新时在当前时间窗口数据的完整性,需额外多存储一些数据,可以存储近35分钟的数据。series.data 的数据的存储形式采用[ {name: '', vlaue: [] }, ... ]的形式, data中的每一个数据对象的name必须唯一;
- 设置option中的xAxis,通过实时改变min 和 max的值来进行窗口移动
实现代码
let charts = {
unit: 'kW',
names: ['name1', 'name2', 'name3'],
value: [[], [], []],
};
let color = ['rgba(79,154,255', 'rgba(75,243,255', 'rgba(255,168,0'];
let lineY = [];
const axisInterval = 30; // 折线图显示时间区间大小(分钟)
watch(
() => props.dataSource,
() => {
if (!props.dataSource) {
return;
}
lineY = [];
/***************************使用数组存储近35分钟曲线数据**************************/
for (let i = 0; i < charts.names.length; i++) {
let x = i;
if (x > color.length - 1) {
x = color.length - 1;
}
if (
charts.value[0].length > 0 &&
(dateUtil(charts.value[0][charts.value[0].length - 1].value[0]).valueOf() -
dateUtil(charts.value[0][0].value[0]).valueOf()) /
1000 /
60 >=
axisInterval + 5
) {
charts.value[i].shift();
charts.value[i].push({
name: `${props.dataSource[i].name}-${props.dataSource[i].time}`,
value: [props.dataSource[i].time, props.dataSource[i].value],
});
} else {
charts.value[i].push({
name: `${props.dataSource[i].name}-${props.dataSource[i].time}`,
value: [props.dataSource[i].time, props.dataSource[i].value],
});
}
/*************************配置series数据**************************/
let cureData = {
name: charts.names[i],
type: 'line',
color: color[x] + ')',
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: color[x] + ', 0.3)',
},
{
offset: 0.8,
color: color[x] + ', 0)',
},
],
false,
),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10,
},
symbolSize: 0,
data: charts.value[i],
};
lineY.push(cureData);
}
/*************************配置options数据**************************/
setOptions({
grid: {
left: 10,
right: 10,
top: 40,
bottom: 10,
containLabel: true,
},
tooltip: {
show: true,
trigger: 'axis',
textStyle: {
color: '#fff',
},
borderColor: '#32e0da',
backgroundColor: 'rgba(0,0,0,0.2)', // 背景
padding: [8, 10], //内边距
extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影
},
legend: {
top: 10,
right: 10,
icon: 'rect',
textStyle: {
color: '#d5d5d5',
},
},
xAxis: {
type: 'time',
// 不满30分钟时,x轴最小值为即是数据最小时间
// 30分钟后,x轴最小值为最大值(即当前时间)减去时间窗口间隔(30)
min: function (value) {
if (value.max - value.min < 1000 * 60 * axisInterval) {
return value.min;
} else {
return value.max - 1000 * 60 * axisInterval;
}
},
// 不满30分钟时,x轴最大值为最小值加上时间窗口间隔(30)
// 30分钟后,x轴最小值为最大值(即当前时间)加上一小段间隔,以保证最新数据
// 与则线图右框保持一定间隔。
max: function (value) {
if (value.max - value.min < 1000 * 60 * axisInterval) {
return value.min + 1000 * 60 * axisInterval;
} else {
return value.max + 1000 * 60 * axisInterval * 0.033;
}
},
splitNumber: 5,
boundaryGap: false, // 横坐标两边不需要留白
axisLine: {
lineStyle: {
color: '#18649e',
width: 2,
},
},
axisLabel: {
// rotate: 40,
margin: 16,
color: '#fff',
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
name: 'kW',
min: 0,
max: 400,
nameTextStyle: {
color: '#fff',
verticalAlign: 'middle',
},
axisLabel: {
// rotate: 40,
margin: 16,
color: '#fff',
},
axisLine: {
show: true,
lineStyle: {
color: '#18649e',
width: 2,
},
},
splitLine: {
lineStyle: {
color: '#224180',
type: 'dashed',
},
},
},
series: lineY,
});
},
{ immediate: true },
);