fix: 回到顶部按钮用 IntersectionObserver 检测+scrollIntoView

- 顶部放哨兵元素,离开视口时显示回到顶部按钮
- 点击用 scrollIntoView 替代 window.scrollTo,兼容各种布局

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-02 00:05:42 +08:00
parent 54c8449f7b
commit 1d8e827374

View File

@@ -196,18 +196,20 @@ export default function MonitoringView() {
return () => observer.disconnect(); return () => observer.disconnect();
}, []); }, []);
// 回到顶部按钮 // 回到顶部按钮:用 IntersectionObserver 检测顶部哨兵是否离开视口
const topSentinelRef = useRef<HTMLDivElement>(null);
useEffect(() => { useEffect(() => {
const handleScroll = () => { const el = topSentinelRef.current;
const scrollY = window.scrollY || document.documentElement.scrollTop; if (!el) return;
setShowBackToTop(scrollY > 400); const observer = new IntersectionObserver(
}; ([entry]) => setShowBackToTop(!entry.isIntersecting),
window.addEventListener('scroll', handleScroll, { passive: true }); );
return () => window.removeEventListener('scroll', handleScroll); observer.observe(el);
return () => observer.disconnect();
}, []); }, []);
const scrollToTop = () => { const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' }); topSentinelRef.current?.scrollIntoView({ behavior: 'smooth' });
}; };
const filteredVehicles = vehicles; const filteredVehicles = vehicles;
@@ -228,6 +230,9 @@ export default function MonitoringView() {
return ( return (
<> <>
{/* 顶部哨兵:离开视口时显示回到顶部按钮 */}
<div ref={topSentinelRef} className="h-0" />
{/* Fullscreen Landscape View Overlay */} {/* Fullscreen Landscape View Overlay */}
<AnimatePresence> <AnimatePresence>
{isFullscreen && ( {isFullscreen && (