大致的场景如下图,点击右侧导购跳转相对应得模块,简单记录一下遇到的问题以及最后的实现办法
1677141083544.jpg
一、实现点击跳转
最开始是用的scrollIntoView来实现跳转,确实用法简单且自带滑动效果,方法如下:
const jumpHeight = (id, index) => {
setActiveIndex(index)
document.getElementById(id).scrollIntoView({
behavior: "smooth"
})
}
但是会造成头部被遮盖滚动不下来的问题,后面改用scrollTop实现,getBoundingClientRect()可获取DOM元素到浏览器可视范围的距离,如下
const jumpHeight = (id, index) => {
setActiveIndex(index)
let scrollTop = document.documentElement.scrollTop +
document.getElementById(id).getBoundingClientRect().top
document.documentElement.scrollTop = scrollTop
}
二、实现滑动滚动条高亮锚点
一开始使用getBoundingClientRect()的top高度来计算对应的高亮,如下
const scrollChange = () => {
let part1 = document.getElementById('baseBox').getBoundingClientRect()
let part2 = document.getElementById('riskBox').getBoundingClientRect()
let part3 = document.getElementById('reliabilityBox').getBoundingClientRect()
if (part1.top === 0) {
setActiveIndex(0)
} else if (part2.top <= 25 && part2.top >= 1) {
setActiveIndex(1)
} else (part3.top <= 30 && part3.top >= 10) {
setActiveIndex(2)
}
}
随后发现从上往下滑动没问题,但是从下往上滑动会有不精确的问题,所以后面改用IntersectionObserver实现,如下
//找到所有的模块节点,放到数组
const boxList = navigationList.map(item => document.getElementById(item.id))
// 开始监听
let arr = []
var io = new IntersectionObserver((entries) => {
entries.forEach((i, index) => {
arr.push({ intersectionRatio: i.intersectionRatio, index: index })
})
// 节点露出比例排序
arr.sort((a, b) => a.intersectionRatio < b.intersectionRatio ? 1 : a.intersectionRatio > b.intersectionRatio ? -1 : 0)
setActiveIndex(arr[0].index)//高亮该锚点
}, {
root: null,
threshold: 1, // 阀值设为1,当只有比例达到1时才触发回调函数
})
// observe遍历监听所有节点
boxList.forEach(box => io.observe(box))
三、完整代码
//导航栏
const NavigationBar = () => {
const [activeIndex, setActiveIndex] = useState(0)
const navigationList = [
{
img: require('../../img/flow_navigation_icons_1.png'),
text: '基本信息',
id: 'baseBox',
},
{
img: require('../../img/flow_navigation_icons_2.png'),
text: '风险结论',
id: 'riskBox'
},
{
img: require('../../img/flow_navigation_icons_3.png'),
text: '可信度分析',
id: 'reliabilityBox'
},
{
img: require('../../img/flow_navigation_icons_4.png'),
text: '流水评估',
id: 'flowBox'
},
{
img: require('../../img/flow_navigation_icons_5.png'),
text: '风险提示',
id: 'tipBox'
},
{
img: require('../../img/flow_navigation_icons_6.png'),
text: '营销反哺',
id: 'marketBox'
}
]
useEffect(() => {
window.addEventListener('scroll', scrollChange)
}, [])
// 窗口滚动事件
const scrollChange = () => {
//找到所有的模块节点,放到数组
const boxList = navigationList.map(item => document.getElementById(item.id))
// 开始监听
let arr = []
var io = new IntersectionObserver((entries) => {
entries.forEach((i, index) => {
arr.push({ intersectionRatio: i.intersectionRatio, index: index })
})
// 节点露出比例排序
arr.sort((a, b) => a.intersectionRatio < b.intersectionRatio ? 1 : a.intersectionRatio > b.intersectionRatio ? -1 : 0)
setActiveIndex(arr[0].index)//高亮该锚点
}, {
root: null,
threshold: 1, // 阀值设为1,当只有比例达到1时才触发回调函数
})
// observe遍历监听所有节点
boxList.forEach(box => io.observe(box))
}
// 跳转页面高度
const jumpHeight = (id, index) => {
setActiveIndex(index)
let scrollTop = document.documentElement.scrollTop + document.getElementById(id).getBoundingClientRect().top
document.documentElement.scrollTop = scrollTop
}
return (
<div className="page-navigation">
{
navigationList.map((item, index) => {
return (
<div className="navigation-box" key={item.id} onClick={() => { jumpHeight(item.id, index) }}>
<img src={item.img} alt="" />
<span className={activeIndex === index ? 'active' : ''}>{item.text}</span>
</div>
)
})
}
</div >
)
}