Shape Divider滚动触发弯曲动画实现方法咨询
嘿,刚好我研究过类似的效果,给你拆解下具体怎么实现~首先先告诉你这个组件的专业名称:滚动驱动SVG形状分隔器(Scroll-driven SVG Shape Divider),核心就是用SVG的可编辑路径结合滚动状态来实现形变。
核心实现逻辑拆解
1. 先搞定基础的形状分隔器
首先你需要用SVG来绘制初始状态的分隔器(就是停止滚动时的平滑曲线)。SVG的<path>元素是关键,它通过d属性定义路径的形状,你可以用在线路径生成工具做出你想要的初始曲线,就像你提供的图片里那种平滑的波浪/曲线分隔线。
2. 滚动时的形变触发
这里有两种主流实现方式,看你更习惯用JS还是CSS:
- JS监听滚动的方式:
- 监听
scroll事件,同时用定时器判断滚动是否停止(避免频繁触发性能浪费)。 - 滚动时,根据滚动的方向/速度,动态修改SVG路径
d属性里的控制点坐标——比如把曲线中间的控制点向上或向下偏移,让分隔线产生弯曲的效果。 - 举个简化的例子:如果初始路径里有个控制点是
C384,75,向下滚动时改成C384,85让曲线凸起,向上滚动时改成C384,65让曲线凹陷。
- 监听
- CSS滚动驱动动画(更现代):
- 现在主流浏览器已经支持CSS滚动驱动动画了,不用写太多JS。你可以给路径的
d属性写关键帧动画,绑定页面滚动进度。 - 比如定义一个从“初始平滑曲线”到“弯曲曲线”再回到“初始曲线”的关键帧,然后用
animation-timeline: scroll(root)把动画和滚动绑定,设置好动画触发的滚动范围(比如滚动0到200px时生效)。
- 现在主流浏览器已经支持CSS滚动驱动动画了,不用写太多JS。你可以给路径的
3. 停止滚动后恢复初始形态
- 如果用JS的话:在滚动停止后(比如设置300ms的延迟,判断没有新的滚动事件就触发),用
requestAnimationFrame把路径的控制点逐步过渡回初始值,而不是一下子跳回去,这样动画会更自然流畅。 - 如果用CSS的话:只要把动画的缓动效果调对(比如用
ease-out),当滚动停止时,动画会自动平滑回到初始状态,不用额外处理。
给你个简化的JS示例参考
先写HTML里的SVG:
<svg class="shape-divider" viewBox="0 0 1440 100" preserveAspectRatio="none"> <path class="divider-path" d="M0,64L48,69.3C96,75,192,85,288,80C384,75,480,53,576,48C672,43,768,53,864,64C960,75,1056,85,1152,80C1248,75,1344,53,1392,42.7L1440,32L1440,100L1392,100C1344,100,1248,100,1152,100C1056,100,960,100,864,100C768,100,672,100,576,100C480,100,384,100,288,100C192,100,96,100,48,100L0,100Z" fill="#ffffff"></path> </svg>
然后是JS逻辑:
const dividerPath = document.querySelector('.divider-path'); const initialD = dividerPath.getAttribute('d'); let scrollTimer; let lastScrollY = window.scrollY; window.addEventListener('scroll', () => { // 清除定时器,标记正在滚动 clearTimeout(scrollTimer); // 判断滚动方向 const currentScrollY = window.scrollY; const scrollDirection = currentScrollY > lastScrollY ? 1 : -1; lastScrollY = currentScrollY; // 简单修改路径控制点,实现弯曲效果(实际可以根据你的路径精准调整) let modifiedD; if (scrollDirection === 1) { // 向下滚动,让曲线凸起 modifiedD = initialD.replace(/80C384,75/g, '90C384,85'); } else { // 向上滚动,让曲线凹陷 modifiedD = initialD.replace(/80C384,75/g, '70C384,65'); } dividerPath.setAttribute('d', modifiedD); // 滚动停止300ms后,平滑恢复初始形状 scrollTimer = setTimeout(() => { // 用requestAnimationFrame做平滑过渡 const animateBack = () => { const currentD = dividerPath.getAttribute('d'); if (currentD === initialD) return; dividerPath.setAttribute('d', initialD); requestAnimationFrame(animateBack); }; animateBack(); }, 300); }, false);
这个示例是简化版,实际你可以根据自己的SVG路径,调整更细腻的控制点变化,甚至结合滚动速度来控制弯曲的幅度,效果会更接近目标网站。
自学的话可以先从修改SVG路径的控制点开始,慢慢调试,熟悉了之后再尝试CSS滚动驱动的方法,会更高效~
内容的提问来源于stack exchange,提问作者jaynejei
相关产品推荐
相关产品推荐

