import React, { useState, useEffect, useRef } from 'react';
interface CarouselNotificationProps {
messages: string[]; // 消息列表
direction?: 'left' | 'right' | 'up' | 'down'; // 动画方向
duration?: number; // 动画持续时间(秒)
interval?: number; // 动画间隔时间(秒)
className?: string; // 自定义类名
type?: string; // 动画类型
}
const CarouselNotification: React.FC<CarouselNotificationProps> = ({ messages, direction = 'left', interval = 2, duration = 5, className = '', type = 'ease-in-out' }) => {
const [currentIndex, setCurrentIndex] = useState<number>(0);
const [message, setMessage] = useState<string>(messages[currentIndex]);
const messageRef = useRef<HTMLDivElement | null>(null);
let timer: NodeJS.Timeout | null = null; // 定时器
// 根据方向获取动画类名
const getAnimationClass = () => {
switch (direction) {
case 'left':
return 'animate-left';
case 'right':
return 'animate-right';
case 'up':
return 'animate-up';
case 'down':
return 'animate-down';
default:
return 'animate-left';
}
};
// 添加初始位置样式
const getInitialPosition = () => {
switch (direction) {
case 'left':
return 'translateX(100%)'
case 'right':
return 'translateX(-100%)'
case 'up':
return 'translateY(100%)'
case 'down':
return 'translateY(-100%)'
default:
return 'translateX(0%)'
}
};
// 动画结束时的处理
const handleAnimationEnd = () => {
messageRef.current?.classList.remove(getAnimationClass());
messageRef.current?.setAttribute('style', `transform: ${getInitialPosition()}`);
timer = setTimeout(() => {
let currIndex = currentIndex + 1;
if (currIndex >= messages.length) {
currIndex = 0;
}
setCurrentIndex(currIndex);
setMessage(messages[currIndex]);
}, interval * 1000);
};
useEffect(() => {
messageRef.current?.classList.add(getAnimationClass());
return () => {
clearTimeout(timer as NodeJS.Timeout);
}
}, [messages, currentIndex]);
return (
<>
<div className='w-full h-full relative overflow-hidden'>
<div className={`initial-position absolute w-full h-full flex items-center justify-center ${className}`}
ref={messageRef}
onAnimationEnd={handleAnimationEnd}
>
{message}
</div>
</div>
<style>
{`
/* 基础样式 */
.initial-position {
transform: ${getInitialPosition()};
}
/* 从右向左动画 */
@keyframes slideLeft {
0% {
transform: translateX(100%);
}
50% {
transform: translateX(0%);
}
100% {
transform: translateX(-100%);
}
}
.animate-left {
animation: slideLeft ${duration}s ${type};
}
/* 从左向右动画 */
@keyframes slideRight {
0% {
transform: translateX(-100%);
}
50% {
transform: translateX(0);
}
100% {
transform: translateX(100%);
}
}
.animate-right {
animation: slideRight ${duration}s ${type};
}
/* 从上向下动画 */
@keyframes slideDown {
0% {
transform: translateY(-100%);
}
50% {
transform: translateY(0);
}
100% {
transform: translateY(100%);
}
}
.animate-down {
animation: slideDown ${duration}s ${type};
}
/* 从下向上动画 */
@keyframes slideUp {
0% {
transform: translateY(100%);
}
50% {
transform: translateY(0);
}
100% {
transform: translateY(-100%);
}
}
.animate-up {
animation: slideUp ${duration}s ${type};
}
`}
</style>
</>
);
};
export default CarouselNotification;
import CarouselNotification from "./CarouseNotification";
export default function Example() {
const messages = [
"1、欢迎来到我们的网站!",
"2、今天的天气非常不错。",
"3、我们有新的优惠活动,请查看。",
"4、感谢您的支持,祝您购物愉快!",
'5、这是另一个消息',
'6、这是一条测试消息',
'7、最新的产品已经上市了',
];
return (
<div className="min-h-screen bg-gray-100 p-8">
<div style={{ padding: '20px', width: '100%', display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'column', gap: '50px' }}>
<h1>轮播消息通知</h1>
<h2>从右向左滚动</h2>
<CarouselNotification messages={messages} interval={1} duration={5} direction="left" />
<h2>从左向右滚动</h2>
<CarouselNotification messages={messages} duration={5} direction="right" />
<h2>从上向下滚动</h2>
<CarouselNotification messages={messages} duration={3} direction="down" />
<h2>从下向上滚动</h2>
<CarouselNotification messages={messages} duration={3} direction="up" />
</div>
</div>
)
}