上传文件至 ui components/sticknav

This commit is contained in:
2025-05-09 00:16:42 +00:00
parent 62671bc737
commit 4a3b645980
2 changed files with 203 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
/* 基础样式 */
.container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
font-family: Arial, sans-serif;
}
.title {
margin-bottom: 10px;
}
.subtitle {
margin-bottom: 40px;
color: #666;
}
/* 粘性导航样式 */
.sticky-nav {
position: sticky;
top: 0;
background-color: white;
padding: 15px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
z-index: 100;
}
.search-box {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ddd;
border-radius: 4px;
}
.category-tabs {
display: flex;
gap: 10px;
overflow-x: auto;
padding-bottom: 5px;
}
.category-tabs button {
padding: 8px 16px;
border: none;
background-color: #f0f0f0;
border-radius: 20px;
cursor: pointer;
white-space: nowrap;
}
.category-tabs button.active {
background-color: #007bff;
color: white;
}
/* 内容区域样式 */
.content-section {
margin-top: 40px;
padding: 20px;
border: 1px solid #eee;
border-radius: 8px;
}
.content-section h2 {
margin-bottom: 15px;
}
/* 占位内容,使页面可滚动 */
.placeholder {
height: 300px;
background: linear-gradient(to bottom, #f9f9f9, #e9e9e9);
margin-top: 20px;
border-radius: 8px;
}

View File

@@ -0,0 +1,128 @@
import React, { useState, useEffect, useRef } from 'react';
import './StickyNavExample.css';
/**
* 最小化示例:实现滚动吸顶与分类高亮效果
*/
const StickyNavExample = () => {
// 分类数据
const categories = [
{ id: 'section1', name: '分类一' },
{ id: 'section2', name: '分类二' },
{ id: 'section3', name: '分类三' },
{ id: 'section4', name: '分类四' },
];
// 状态管理
const [activeSection, setActiveSection] = useState(categories[0].id);
const isManualScrollRef = useRef(false);
const timerRef = useRef(null);
// 监听滚动事件,更新当前活动分类
useEffect(() => {
const handleScroll = () => {
// 如果是手动点击导致的滚动,则跳过自动检测
if (isManualScrollRef.current) return;
const stickyNav = document.querySelector('.sticky-nav');
const stickyHeight = stickyNav?.getBoundingClientRect().height || 0;
const triggerOffset = stickyHeight + 20; // 触发点位置
// 遍历所有分类区块,检查哪个在视口中
categories.forEach(category => {
const section = document.getElementById(category.id);
if (section) {
const rect = section.getBoundingClientRect();
// 当区块顶部进入触发点时,将其设为当前活动分类
if (rect.top <= triggerOffset && rect.bottom >= triggerOffset) {
setActiveSection(category.id);
}
}
});
};
// 添加滚动事件监听
window.addEventListener('scroll', handleScroll);
// 组件卸载时移除事件监听
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// 处理分类点击事件
const handleCategoryClick = (categoryId) => {
// 清除之前的定时器
if (timerRef.current) {
clearTimeout(timerRef.current);
}
// 设置为手动滚动,暂时禁用自动检测
isManualScrollRef.current = true;
setActiveSection(categoryId);
// 滚动到对应区块
const section = document.getElementById(categoryId);
const stickyNav = document.querySelector('.sticky-nav');
if (section && stickyNav) {
const stickyHeight = stickyNav.getBoundingClientRect().height;
const sectionTop = section.offsetTop - stickyHeight;
window.scrollTo({
top: sectionTop,
behavior: 'smooth'
});
}
// 设置定时器1秒后重新启用滚动检测
timerRef.current = setTimeout(() => {
isManualScrollRef.current = false;
}, 1000);
};
return (
<div className="container">
{/* 页面标题 */}
<h1 className="title">滚动吸顶示例</h1>
<p className="subtitle">向下滚动查看效果</p>
{/* 粘性导航区域 */}
<div className="sticky-nav">
{/* 搜索框 */}
<input
type="text"
className="search-box"
placeholder="搜索..."
/>
{/* 分类标签 */}
<div className="category-tabs">
{categories.map(category => (
<button
key={category.id}
className={activeSection === category.id ? 'active' : ''}
onClick={() => handleCategoryClick(category.id)}
>
{category.name}
</button>
))}
</div>
</div>
{/* 内容区域 */}
{categories.map(category => (
<div
key={category.id}
id={category.id}
className="content-section"
>
<h2>{category.name}</h2>
<p>这是{category.name}的内容区域滚动时当此区域进入视口中间位置对应的分类标签会自动高亮</p>
{/* 添加一些占位内容使页面可滚动 */}
<div className="placeholder"></div>
</div>
))}
</div>
);
};
export default StickyNavExample;