From d5d6c1e87be7427f62db0b795b3ac4e1003cd954 Mon Sep 17 00:00:00 2001 From: mtvpls Date: Wed, 10 Jun 2026 22:21:33 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E8=BD=AE=E6=92=AD=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E8=87=AA=E9=80=82=E5=BA=94=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/BannerCarousel.tsx | 68 +++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/components/BannerCarousel.tsx b/src/components/BannerCarousel.tsx index 5d22ee5..4f3e085 100644 --- a/src/components/BannerCarousel.tsx +++ b/src/components/BannerCarousel.tsx @@ -9,7 +9,13 @@ import { } from 'lucide-react'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { + useCallback, + useEffect, + useLayoutEffect, + useRef, + useState, +} from 'react'; import { type TMDBItem, @@ -66,14 +72,19 @@ export default function BannerCarousel({ const [isMuted, setIsMuted] = useState(true); // 视频是否静音(默认静音) const [bannerHeightScale, setBannerHeightScale] = useState('1'); // 轮播图高度倍率 + const [isMobileView, setIsMobileView] = useState(false); + const [mobileTitleFontSize, setMobileTitleFontSize] = useState(30); const videoRef = useRef(null); // 视频元素引用 const videoRefs = useRef>(new Map()); // 所有视频元素的引用 + const titleRef = useRef(null); + const titleTextRef = useRef(null); const touchStartX = useRef(0); const touchEndX = useRef(0); const isManualChange = useRef(false); // 标记是否为手动切换 // LocalStorage 缓存配置 const LOCALSTORAGE_DURATION = 24 * 60 * 60 * 1000; // 1天 + const currentTitle = items[currentIndex]?.title || ''; // 根据数据源获取缓存key const getLocalStorageKey = (source: string) => { @@ -141,6 +152,49 @@ export default function BannerCarousel({ }; }, []); + // 检测移动端视口,用于 1x 高度下的标题自适应 + useEffect(() => { + const updateIsMobileView = () => { + setIsMobileView(window.innerWidth < 768); + }; + + updateIsMobileView(); + window.addEventListener('resize', updateIsMobileView); + return () => window.removeEventListener('resize', updateIsMobileView); + }, []); + + // 手机界面且轮播图高度为 1x 时,仅在标题超过一行时自动缩小字号,不改变布局位置 + useLayoutEffect(() => { + const titleElement = titleRef.current; + const titleTextElement = titleTextRef.current; + if (!titleElement || !titleTextElement) return; + + if (bannerHeightScale !== '1' || !isMobileView) { + titleElement.style.fontSize = ''; + setMobileTitleFontSize(30); + return; + } + + const maxFontSize = 30; + const minFontSize = 12; + let nextFontSize = maxFontSize; + + titleElement.style.fontSize = `${nextFontSize}px`; + + while ( + nextFontSize > minFontSize && + titleTextElement.getClientRects().length > 1 + ) { + nextFontSize -= 1; + titleElement.style.fontSize = `${nextFontSize}px`; + } + + titleElement.style.fontSize = `${nextFontSize}px`; + setMobileTitleFontSize(nextFontSize); + + return undefined; + }, [bannerHeightScale, currentTitle, isMobileView]); + // 延迟加载:等待页面加载完毕后再开始加载轮播图数据 useEffect(() => { if (!delayLoad) return; @@ -529,8 +583,16 @@ export default function BannerCarousel({ {/* 内容信息 */}
-

- {currentItem.title} +

+ {currentItem.title}