我这里的需求是每一分钟请求一次接口获取新增信息,然后按照新增信息依次弹出气泡,这里的气泡需要根据区域坐标来定位,所以最后选择使用自定义toolTip来实现。
关键代码:
const [queue, setQueue] = useState([]);
let queueIndex = 0;
// 每分钟请求的接口
const { data: orderData } = useSWR('/get_central_maps', getOrderData, {
refreshInterval: 1000 * 60, revalidateIfStale: true,
onSuccess: (res) => {
setQueue(res.map.area || [])
queueIndex = 0; // 恢复序列,重新开始循环气泡动画
}
})
// 获取到数据后定时弹出气泡
useEffect(() => {
const playMapTooltipInterval = setInterval(() => {
if (queueIndex < queue.length) {
if (!myChart) {
const mapDom = document.getElementById("map");
if (mapDom) {
myChart = echarts.init(mapDom);
}
}
let option = myChart.getOption();
let item = queue[queueIndex];
option.series[0].tooltip.formatter = (params) => {
if (!queue.length || item.n !== params.name) { return "" } else {
return `<div>
<div class="${styles.mapTooltipNum}">${item.n}订单量 +${item?.count}</div>
<div class="${styles.mapTooltipMoney}">${item.n}营业额 +${item?.price}</div>
</div>`
}
}
myChart.setOption(option);
myChart.dispatchAction({
type: 'showTip',
seriesIndex: 0,
name: item.n,
});
queueIndex++;
} else {
clearInterval(playMapTooltipInterval); // 如果队列为空,则停止循环
}
}, 3000);
return () => clearInterval(playMapTooltipInterval); // 清除定时器
}, [queue]);
自定义toolTip的css:
.mapTooltipMoney {
border: 1px solid red;
font-size: 20px;
position: absolute;
left: 0;
transform: translate(-50%, -50%);
background: linear-gradient(238deg, #8E53CF, #674ECF);
animation: fade 1.5s ease-in-out forwards;
color:#fff;
opacity: 0;
animation-delay:1s;
margin-top: -1rem;
padding: 2px 20px;
border-radius: 8px;
border: 1px solid #FFFFFF;
font-size: 15px;
}
.mapTooltipNum {
border: 1px solid red;
font-size: 20px;
position: absolute;
margin-top: -1rem;
left: 0;
top: 0px;
margin-top: -20px;
transform: translate(-50%, -50%);
animation: fade 1.5s ease-in-out forwards;
background: linear-gradient(238deg, #FD8B23, #FF3061);
color:#fff;
padding: 2px 20px;
border-radius: 8px;
border: 1px solid #FFFFFF;
font-size: 15px;
}
@keyframes fade {
0% {
opacity: 0;
top: 20px;
}
50% {
opacity: 1;
top: 10px;
}
100% {
opacity: 0;
top: 0px;
}
}