ReactJS如何实现滚动时div从左向右移动且停留在所属区块内
实现代码
JSX 部分
import { useState, useEffect, useRef } from 'react' // 可根据自身需求调整以下常量 const ROOT_FONT_SIZE = 16 // 项目根元素font-size,默认浏览器为16px const INITIAL_LEFT = 2 // 圆形初始左侧位置,单位rem const MOVE_SPEED = 5 // 移动速度,数值越大移动越慢 function App() { const [position, setPosition] = useState(INITIAL_LEFT) const sectionRef = useRef(null) const circleRef = useRef(null) const maxLeftRef = useRef(0) // 页面加载完成后计算圆形可移动的最大右边界 useEffect(() => { const sectionWidth = sectionRef.current.offsetWidth const circleWidth = circleRef.current.offsetWidth maxLeftRef.current = (sectionWidth - circleWidth) / ROOT_FONT_SIZE }, []) function moveCircle() { const scrollTop = window.pageYOffset const candidatePosition = scrollTop / MOVE_SPEED // 仅新位置大于当前位置且未超出边界时更新,实现向上滚动不回退 if (candidatePosition > position && candidatePosition < maxLeftRef.current) { setPosition(candidatePosition) } // 到达右边界后固定位置不再移动 else if (candidatePosition >= maxLeftRef.current && position !== maxLeftRef.current) { setPosition(maxLeftRef.current) } } useEffect(() => { const scrollHandler = () => requestAnimationFrame(moveCircle) window.addEventListener('scroll', scrollHandler, false) // 组件卸载时清理滚动监听,避免内存泄漏 return () => window.removeEventListener('scroll', scrollHandler) }, [position]) return ( <div className="App"> <div className="sectionOne" ref={sectionRef}> <div className="circle styles" ref={circleRef} style={{ position: 'absolute', left: `${position}rem` }} ></div> </div> <div className="sectionTwo"></div> </div> ) } export default App
CSS 补充
.sectionOne { position: relative; /* 必须设置,保证圆形相对于当前区块定位 */ height: 150vh; /* 可自行调整高度,需要足够的滚动空间触发圆形移动 */ width: 100%; } .circle { /* 以下为示例样式,可根据需求修改 */ width: 4rem; height: 4rem; border-radius: 50%; background-color: #2563eb; top: 50%; transform: translateY(-50%); }
关键逻辑说明
- 父容器必须设置
position: relative,否则圆形的绝对定位会相对于整个页面,而非所属区块 - 通过
useRef获取容器和圆形的实际宽度,自动计算最大可移动右边界,保证圆形不会超出所属区块范围 - 位置更新时新增两个判断:仅向下滚动(新位置大于当前位置)时更新,向上滚动位置不变;到达右边界后直接固定位置,不会滚动出页面
- 新增滚动事件清理逻辑,避免组件卸载后内存泄漏
内容的提问来源于stack exchange,提问作者monkeys773
相关产品推荐
相关产品推荐

