You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 15:03:03