58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
![]() |
// components/Header.tsx
|
||
|
import { motion, useScroll, useTransform } from "framer-motion";
|
||
|
import { useContext, useEffect, useState } from "react";
|
||
|
import { CourseDetailContext } from "../CourseDetailContext";
|
||
|
|
||
|
export const CourseDetailHeader = () => {
|
||
|
const { scrollY } = useScroll();
|
||
|
|
||
|
const [lastScrollY, setLastScrollY] = useState(0);
|
||
|
const { course, isHeaderVisible, setIsHeaderVisible } =
|
||
|
useContext(CourseDetailContext);
|
||
|
useEffect(() => {
|
||
|
const updateHeader = () => {
|
||
|
const current = scrollY.get();
|
||
|
const direction = current > lastScrollY ? "down" : "up";
|
||
|
|
||
|
if (direction === "down" && current > 100) {
|
||
|
setIsHeaderVisible(false);
|
||
|
} else if (direction === "up") {
|
||
|
setIsHeaderVisible(true);
|
||
|
}
|
||
|
|
||
|
setLastScrollY(current);
|
||
|
};
|
||
|
|
||
|
// 使用 requestAnimationFrame 来优化性能
|
||
|
const unsubscribe = scrollY.on("change", () => {
|
||
|
requestAnimationFrame(updateHeader);
|
||
|
});
|
||
|
|
||
|
return () => {
|
||
|
unsubscribe();
|
||
|
};
|
||
|
}, [lastScrollY, scrollY, setIsHeaderVisible]);
|
||
|
|
||
|
return (
|
||
|
<motion.header
|
||
|
initial={{ y: 0 }}
|
||
|
animate={{ y: isHeaderVisible ? 0 : -100 }}
|
||
|
transition={{ type: "spring", stiffness: 300, damping: 30 }}
|
||
|
className="fixed top-0 left-0 w-full h-16 bg-slate-900 backdrop-blur-sm z-50 shadow-sm">
|
||
|
<div className="w-full mx-auto px-4 h-full flex items-center justify-between">
|
||
|
<div className="flex items-center space-x-4">
|
||
|
<h1 className="text-white text-xl ">{course?.title}</h1>
|
||
|
</div>
|
||
|
<nav className="flex items-center space-x-4">
|
||
|
{/* 添加你的导航项目 */}
|
||
|
<button className="px-4 py-2 rounded-full bg-blue-500 text-white hover:bg-blue-600 transition-colors">
|
||
|
开始学习
|
||
|
</button>
|
||
|
</nav>
|
||
|
</div>
|
||
|
</motion.header>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
export default CourseDetailHeader;
|