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