React实现向下滚动时图片拉宽、向上滚动还原的动画效果
React 滚动触发图片拉宽动画实现方案
核心逻辑
监听页面滚动行为,实时计算图片元素在视口中的位置,将滚动进度映射为图片宽度值,配合CSS过渡属性实现平滑动画:向下滚动时图片宽度随滚动距离逐步拉宽,向上滚动时宽度随位置回退自然恢复初始状态。
具体实现
1. 编写基础样式
给外层容器和图片设置基础属性,提前定义过渡效果,避免图片缩放时变形:
.article-wrapper { min-height: 120vh; display: flex; align-items: center; justify-content: center; padding: 20vh 0; } .image { /* 初始宽度可按业务需求调整 */ width: 60%; height: 600px; object-fit: cover; /* 平滑过渡参数可自行调整,控制动画快慢 */ transition: width 0.25s ease-out; will-change: width; }
如果你已经给
ArticleWrapper写过布局样式,直接复用现有样式即可,不需要重复编写。
2. 组件逻辑实现
通过ref获取图片DOM节点,绑定滚动监听事件,用requestAnimationFrame做节流优化,实时计算滚动进度并同步更新图片宽度,完全适配你现有的代码结构:
import { useEffect, useRef, useState } from 'react'; import Img from './your-image-asset.png'; // 引入你项目中已有的ArticleWrapper组件 import ArticleWrapper from './your-component-path'; const ScrollImageSection = () => { const imageRef = useRef(null); const [widthPercent, setWidthPercent] = useState(60); useEffect(() => { let ticking = false; const calcImageWidth = () => { if (!imageRef.current) return; const rect = imageRef.current.getBoundingClientRect(); const viewportH = window.innerHeight; // 定义动画触发的滚动区间,数值越大动画越平缓 const triggerRange = viewportH * 0.6; // 计算0-1区间的滚动进度 let progress = (viewportH - rect.top) / (viewportH + triggerRange); progress = Math.min(Math.max(progress, 0), 1); // 映射宽度:初始60%,最大100%,可按需修改数值 setWidthPercent(60 + progress * 40); ticking = false; }; // 初始化计算首屏位置 calcImageWidth(); const scrollHandler = () => { if (!ticking) { window.requestAnimationFrame(calcImageWidth); ticking = true; } } window.addEventListener('scroll', scrollHandler, { passive: true }); // 组件卸载时移除事件监听,避免内存泄漏 return () => window.removeEventListener('scroll', scrollHandler); }, []); return ( <ArticleWrapper> <img ref={imageRef} className="image" src={Img} alt="Section image" style={{ width: `${widthPercent}%` }} /> </ArticleWrapper> ); }; export default ScrollImageSection;
自定义调整说明
- 宽度范围:修改代码中初始宽度值、进度换算的增量值即可调整初始和最大宽度,比如需要最大宽度为90%,就把
progress * 40改成progress * 30 - 动画节奏:调整CSS中
transition的时长、triggerRange的数值,即可控制动画的快慢和触发的滚动距离 - 滚动容器适配:如果页面是内部容器滚动而非全局window滚动,将滚动事件绑定到对应容器DOM上即可,计算逻辑完全一致
- 性能保障:代码已通过requestAnimationFrame节流、passive事件监听、will-change属性做了性能优化,正常页面场景下不会出现卡顿
内容的提问来源于stack exchange,提问作者Jaacoubi
相关产品推荐
相关产品推荐

