目前需求是要做散点图,但要求不能重叠,得横着排,这就很为难,因为我的轴是时间轴,考虑之后打算采取柱状图的方式去实现,隐藏掉柱子,只显示散点图的图标。这就可以完美解决这个问题
需求图:
初步实现效果:
我和后端那边商量在最大放大档是一小时内数据只显示在这个小时的刻度线上,但只要滚轮放大,就显示到真实的点上。当然还是会有重叠的情况,但没必要去考虑的太细,一方面本省就不符合坐标轴的逻辑,第二那我还要考虑视口宽度,太麻烦了,最后还可能吃力不讨好,觉得做到这种程度其实也差不多,至于到秒级事件触发过于频繁,就需要后端那边去处理了,去掉那些重复事件
代码的话有一个地方要注意就是要处理空数据占位的问题,比如我8种点,可能有1、3、7有数据,如果占位就会特别别扭,这就需要居中,网上也有多列柱状图无数据剧中的方案,我的具体代码是这样的:
因为我的代码涉及到具体的业务,就没有粘贴全部,只是关键代码,就是在显示tooltip时,为了能正常显示,所以我还是做了一级不优化居中效果的柱状图,去专门显示
// 有几个要显示的时间点
const xAxis = [
new Date('2024-06-16 13:00:01').getTime(),
new Date('2024-06-16 15:00:00').getTime(),
new Date('2024-06-16 17:00:00').getTime(),
new Date('2024-06-16 19:00:00').getTime(),
];
// 有几种要显示的事件
const bar = [
[10, 2, 0],
[8, 2, 0],
[0, 0, 2],
[0, 0, 2],
[0, 0, 2],
[0, 0, 2],
[0, 0, 2],
[0, 0, 2],
];
function dealBar(arr: Array<number>, name: string) {
const bar: any = [];
arr.forEach((item: number, index: number) => {
const data = [];
for (let i = 0; i < index; i++) {
data.push('');
}
if (item) {
data.push([xAxis[index], item]);
bar.push({
name,
type: 'pictorialBar',
symbolSize: 16,
symbol: 'circle',
xAxisIndex: index + 1,
barWidth: 16,
barGap: 0,
symbolPosition: 'end',
data,
});
}
});
return bar;
}
// echarts
tooltip: {
trigger: 'axis',
alwaysShowContent: false,
axisPointer: {
snap: false,
},
},
xAxis: [
{
type: 'time',
position: 'bottom',
min: timeStart,
max: timeEnd,
axisLabel: {
// 格式化x轴显示
formatter: function (value: any) {
if (level >= 4 && level < 6) {
// 其他的时间返回格式化 00:00
return moment(value).format('HH:mm:ss');
} else if (level >= 6) {
return moment(value).format('HH:mm:ss');
} else {
return moment(value).format('HH:mm');
}
},
},
scale: true,
minInterval: 1,
splitNumber: 10,
splitLine: { show: false },
axisPointer: {
type: 'line',
},
axisTick: { show: false },
},
...xAxis.map(item => {
let data = item;
return {
type: 'time',
position: 'bottom',
data,
min: timeStart,
max: timeEnd,
axisLabel: {
show: false,
// 格式化x轴显示
formatter: function (value: any) {
return moment(value).format('HH:mm');
},
},
splitNumber: 10,
splitLine: { show: false },
axisPointer: {
show: false,
},
axisTick: { show: false },
};
}),
],
// echarts series代码
series: [
...dealBar(bar[0], '气流受限事件'),
...dealBar(bar[1], '参数改变事件'),
...dealBar(bar[2], '阻塞性事件'),
...dealBar(bar[3], '中枢性事件'),
...dealBar(bar[4], '鼾声事件'),
...dealBar(bar[5], '氧减事件'),
...dealBar(bar[6], '低通气事件'),
...dealBar(bar[7], '报警事件'),
// tooltip,为了保证tooltip的正常显示
{
name: '气流受限事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[0].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barWidth: 16,
barGap: 0,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '参数改变事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[1].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '阻塞性事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[2].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '中枢性事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[3].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '鼾声事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[4].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '氧减事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[5].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '低通气事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[6].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
{
name: '报警事件',
type: 'pictorialBar',
symbolSize: 16,
symbol: 'none',
data: bar[7].map((item, index) => {
if (item) {
return [xAxis[index], item];
} else {
return '';
}
}),
barGap: 0,
barWidth: 16,
symbolPosition: 'end',
xAxisIndex: 0,
},
],