"use client"; import { useLayoutEffect, useRef, useState, type ReactNode } from "react"; /** 恒定线速度:px/s,图标多少只影响时长 */ const SCROLL_PX_PER_SEC = 36; type AdIconMarqueeProps = { children: ReactNode; className?: string; /** 段内间距,需与尾部 spacer 对齐以无缝衔接 */ gapClassName?: string; /** 段尾 spacer 宽度,应等于 gap(gap-2→w-2,gap-3→w-3) */ spacerClassName?: string; /** 内容签名:列表变化时重算时长 */ contentKey?: string; }; /** Icon 广告从右向左无缝自动滚动(内容复制两段,translateX -50%) */ export function AdIconMarquee({ children, className = "", gapClassName = "gap-3", spacerClassName = "w-3", contentKey = "", }: AdIconMarqueeProps) { const segmentRef = useRef(null); const [durationSec, setDurationSec] = useState(20); useLayoutEffect(() => { const el = segmentRef.current; if (!el) return; const update = () => { const width = el.getBoundingClientRect().width; if (width <= 0) return; setDurationSec(Math.max(width / SCROLL_PX_PER_SEC, 8)); }; update(); const observer = new ResizeObserver(update); observer.observe(el); return () => observer.disconnect(); }, [contentKey]); return (
{children}
{children}
); }