基于GSAP实现随屏幕宽度自适应的滚动触发路径变形裁剪动画问题求助
基于GSAP实现随屏幕宽度自适应的滚动触发路径变形裁剪动画问题求助
背景
最近跟着JsMastery的视频学习时,了解到Zentry网站的一个效果——随滚动触发的动态路径变形裁剪动画,我不想用简单的polygon剪裁路径,想实现类似的、随滚动让容器路径动态变形的效果,目前还没用到MorphSVG插件。
问题描述
我发现Zentry是根据屏幕宽度动态调整剪裁路径的,我先定义了两个关键路径状态(w代表当前屏幕宽度),想实现Hero区域(带视频的区块)的路径变形:
- 初始路径(Step 1):
M ${w} -3 L ${w} -3 Q ${w + 8} -3 ${w + 8} 5 L ${w + 8} 854.422 Q ${w + 8} 862.422 ${w} 862.422 L 5 862.422 Q -3 862.422 -3 854.422 L -3 5 Q -3 -3 5 -3 Z
- 目标路径(Step 2):
M ${0.931 * w - 34.3} 185.647 L ${0.931 * w - 34.3} 185.647 Q ${0.947 * w - 32.8} 186.339 ${0.95 * w - 28.9} 194.137 L ${0.99 * w + 2.2} 786.123 Q ${0.993 * w + 4.0} 793.92 ${0.986 * w + 2.0} 794.063 L ${-0.996 * w + 462.0} 819.577 Q ${-1.0 * w + 460.0} 819.72 ${-0.994 * w + 450.6} 812.027 L ${1.286 * w - 432.0} 98.3966 Q ${1.291 * w - 435.0} 90.7035 ${1.297 * w - 438.5} 91.3961 Z
现在的问题是,我尝试了两种方案都没达到预期效果,想求助怎么正确实现这种随屏幕宽度自适应、同时随滚动触发的路径变形剪裁。
已尝试的解决方案
方案1:自定义Hook结合GSAP ScrollTrigger
我写了一个useResponsivePath自定义Hook,通过useEffect监听窗口resize事件,根据当前屏幕宽度返回初始和目标路径,然后结合GSAP的ScrollTrigger尝试驱动动画:
const clipPathD = useResponsivePath() useGSAP(() => { gsap.set("#video-frame", { clipPath: `path('${clipPathD.initial}')`, }); gsap .timeline({ scrollTrigger: { trigger: "#video-frame", start: "center center", end: "bottom center", scrub: true, }, defaults: { ease: "power1.inOut" }, }) .to("#video-frame", { clipPath: `path('${clipPathD.initial}')`, // 注:这里疑似笔误,应该是目标路径,但当时代码写的是initial,所以无变化 }); });
但这个方案完全没效果,容器的剪裁路径没有任何变化。
方案2:通过SVG的clipPath元素实现
我换了思路,把路径定义在SVG的clipPath元素中,再给目标容器应用这个剪裁规则,然后尝试动画SVG路径的d属性:
useGSAP(() => { gsap.set("#clipPathShape", { attr: { d: paths.initial } }); gsap .timeline({ scrollTrigger: { trigger: "#video-frame", start: "center center", end: "bottom center", scrub: true, }, defaults: { ease: "power1.inOut" }, }) .to("#clipPathShape", { attr: { d: paths.middle } }); });
对应的HTML结构:
<svg width="0" height="0"> <clipPath id="dynamicClip" clipPathUnits="objectBoundingBox"> <path id="clipPathShape" d="[original path i.e. the step 1]" /> </clipPath> </svg> <div id="video-frame" style={{ clipPath: "url(#dynamicClip)", WebkitClipPath: "url(#dynamicClip)" }} > {/* 视频及其他内容 */} </div>
这个方案同样没有生效,滚动时路径没有出现预期的变形效果。
目前我还没处理下方About区域的响应式问题,先聚焦Hero区域的动画实现,想请教各位大佬,我的代码哪里出了问题?或者有没有更合理的实现思路?
内容来源于stack exchange
相关产品推荐
相关产品推荐

