TopSwiperBanner.tsx 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. "use client";
  2. import { useEffect, useState } from "react";
  3. const ITEM_HEIGHT = 40; // h-10 = 40px
  4. const INTERVAL = 3000;
  5. const TRANSITION_DURATION = 500;
  6. const messages = [
  7. "Tax Refund Season, Straight to The Lowest Price! As Low As $99!",
  8. "Free Shipping On Orders Over $99",
  9. "30 Days Easy Return & Exchange",
  10. ];
  11. export default function AnnouncementBar() {
  12. const [index, setIndex] = useState(0);
  13. const [enableTransition, setEnableTransition] = useState(true);
  14. // 最后复制第一条,实现无缝循环
  15. const loopMessages = [...messages, messages[0]];
  16. // 每隔 3 秒向上滚动一条
  17. useEffect(() => {
  18. if (messages.length <= 1) return;
  19. const timer = window.setInterval(() => {
  20. setIndex((prev) => prev + 1);
  21. }, INTERVAL);
  22. return () => {
  23. window.clearInterval(timer);
  24. };
  25. }, []);
  26. // 滚动到复制出来的第一条后,瞬间重置到真正第一条
  27. useEffect(() => {
  28. if (index !== messages.length) return;
  29. const timer = window.setTimeout(() => {
  30. // 先关闭 transition
  31. setEnableTransition(false);
  32. // 瞬间回到第一条
  33. setIndex(0);
  34. // 下一帧重新开启 transition
  35. requestAnimationFrame(() => {
  36. requestAnimationFrame(() => {
  37. setEnableTransition(true);
  38. });
  39. });
  40. }, TRANSITION_DURATION);
  41. return () => {
  42. window.clearTimeout(timer);
  43. };
  44. }, [index]);
  45. return (
  46. <div className="h-10 w-full overflow-hidden bg-[#036141]">
  47. <div
  48. className={
  49. enableTransition
  50. ? "transition-transform duration-500 ease-in-out"
  51. : ""
  52. }
  53. style={{
  54. transform: `translateY(-${index * ITEM_HEIGHT}px)`,
  55. }}
  56. >
  57. {loopMessages.map((message, messageIndex) => (
  58. <div
  59. key={messageIndex}
  60. className="
  61. flex
  62. h-10
  63. items-center
  64. justify-center
  65. px-4
  66. text-center
  67. text-[14px]
  68. font-medium
  69. text-white
  70. "
  71. >
  72. {message}
  73. </div>
  74. ))}
  75. </div>
  76. </div>
  77. );
  78. }