最近在做公司的一个大屏展示页时,要求折线图能够自动滚动,网上大多例子都是基于Echarts实现的,没有适合AntV React的,于是自己动手
import React, { useContext, useEffect } from 'react';
import { Datum, Line } from '@antv/g2plot';
import ProCard from '@ant-design/pro-card';
let ticketCount = 5;
let plot: Line;
const cardStyle = {
backgroundColor: '#16134B',
height: '34vh',
};
//需要展示的数据,实际这个地方的数据有很多很多
const data=[
{
"site_name": "Whiz Demo",
"successful": 100
}
]
const Demo: React.FC = () => {
const containerRef = React.createRef<HTMLElement>();
//最小的数据
let min = 100
//鼠标是否移动到图表区域
let mouseEntered = false;
data.map(res => {
if (res.successful < min) {
min = res.successful
}
})
useEffect(() => {
plot = new Line(containerRef.current!, {
data: data.slice(0, data.length > ticketCount ? ticketCount : data.length),
xField: 'site_name',
yField: 'successful',
padding: 'auto',
autoFit: false,
xAxis: {
label: {
style: {
fill: '#fff',
}
},
},
yAxis: {
min: min - 2,
max: 100,
grid: null,
label: {
formatter: (v: any) => `${parseFloat(v).toFixed(2)}%`,
style: {
fill: '#fff',
}
},
},
tooltip: {
formatter: (datum: Datum) => {
return { name: datum.site_name, value: datum.successful + '%' };
},
},
color: '#FF696D',
smooth: true,
point: {
size: 3
},
});
//添加鼠标进入图表区和离开图表区事件
plot.on('plot:mouseenter', () => {
mouseEntered = true;
});
plot.on('plot:mouseleave', () => {
mouseEntered = false;
});
plot.render();
}, [])
useEffect(() => {
if (data.length <= ticketCount) {
plot.changeData(data);
return;
}
let currentIndex = 0;
//每次保证取5条数据,无限循环[1,2,3,4,5],[2,3,4,5,6],[3,4,5,6,1]...
const getNextFiveData = () => {
const fiveData = [];
for (let i = 0; i < ticketCount; i++) {
const index = (currentIndex + i) % data.length;
fiveData.push(data[index]);
}
currentIndex = (currentIndex + 1) % data.length;
return fiveData;
}
const timer = setInterval(() => {
if (!mouseEntered) {
const newData = getNextFiveData()
plot.changeData(newData);
}
}, 1500);
return () => {
clearInterval(timer);
};
}, [data])
return <ProCard
title='xxxxx'}
style={cardStyle}
>
<div ref={containerRef as React.RefObject<HTMLDivElement>} style={{ width: '100%', height: '100%' }}></div>
</ProCard>;
}
export default Demo;
最终效果