74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef, useState, type CSSProperties } from "react";
|
|
|
|
type AdTextProps = {
|
|
title: string;
|
|
textColor?: string;
|
|
bgColor?: string;
|
|
href?: string;
|
|
className?: string;
|
|
};
|
|
|
|
/**
|
|
* 文字广告:仅当文字宽度超出容器时才启用跑马灯滚动,
|
|
* 能完整显示时居中静止。结构与样式复用侧栏 .j13-ad-text。
|
|
*/
|
|
export function AdText({ title, textColor, bgColor, href, className = "" }: AdTextProps) {
|
|
const trackRef = useRef<HTMLSpanElement>(null);
|
|
const [overflow, setOverflow] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const track = trackRef.current;
|
|
if (!track) return;
|
|
const measure = () => {
|
|
const run = track.querySelector<HTMLElement>(".j13-ad-text-run");
|
|
const container = track.parentElement;
|
|
if (!run || !container) return;
|
|
setOverflow(run.scrollWidth > container.clientWidth);
|
|
};
|
|
measure();
|
|
window.addEventListener("resize", measure);
|
|
return () => window.removeEventListener("resize", measure);
|
|
}, [title]);
|
|
|
|
const cls = `j13-ad-text${overflow ? " is-overflow" : ""}${className ? ` ${className}` : ""}`;
|
|
const style: CSSProperties = { color: textColor, background: bgColor };
|
|
|
|
const inner = (
|
|
<span
|
|
className={`j13-ad-text-track${overflow ? " is-overflow" : ""}`}
|
|
ref={trackRef}
|
|
>
|
|
<span className="j13-ad-text-run">{title}</span>
|
|
{overflow ? (
|
|
<span className="j13-ad-text-run" aria-hidden>
|
|
{title}
|
|
</span>
|
|
) : null}
|
|
</span>
|
|
);
|
|
|
|
if (href) {
|
|
return (
|
|
<a
|
|
href={href}
|
|
target="_blank"
|
|
rel="noopener noreferrer sponsored"
|
|
className={cls}
|
|
style={style}
|
|
data-tip={title}
|
|
>
|
|
{inner}
|
|
</a>
|
|
);
|
|
}
|
|
return (
|
|
<span className={cls} style={style} data-tip={title}>
|
|
{inner}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export default AdText;
|