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

基于GSAP实现滚动触发的SVG多图形平滑变形(三角形→圆形→方形)问题求助

基于GSAP实现滚动触发的SVG多图形平滑变形(三角形→圆形→方形)问题求助

滚动触发的SVG变形效果

我最近在折腾一个滚动触发的SVG变形动画,想实现像参考效果那样,根据滚动方向变化,在不同图形间平滑过渡——先是三角形变圆形,再变方形把侧边拉平。目前我用GSAP做了基础版本,但遇到了不少问题,想请大家帮忙看看:

  • 最初实现了三角形到圆形的变形,但扩展到圆形到方形的步骤时,变形效果特别怪异,侧边像是在突兀地跳转
  • 后来我参考目标效果调整成了菱形→碗形→缩放消失的流程,但新问题又出现了:底部有间隙、变形时对齐不准,而且不知道怎么让第三步的缩放动画等滚动到对应阶段再触发

初始实现代码(三角形→圆形)

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Gsap Scroll Morphing</title>
  <link rel="stylesheet" href="./style.css">
</head>
<body>
  <svg version="1.1" id="svg2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" style="enable-background:new 9 80 800 400;" xml:space="preserve">
    <style type="text/css">
      .st1 {
        fill: black;
      }
    </style>

    <!-- 目标形状:圆形 -->
    <path id="circle" class="st1" d="M 0 0 A 1 1 0 0 0 1000 0" />

    <!-- 初始形状:三角形 -->
    <path id="hippo" class="st1" d="M 0 0 L 500 500 L 1000 0" />

    <div id="v-spacer-1" class="v-spacer"></div>
    <div id="v-spacer-2" class="v-spacer"></div>
    
    <script src='https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.4/gsap.min.js'></script>
    <script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/MorphSVGPlugin3.min.js'></script>
    <script src='https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js'></script>
    <script src="./script.js"></script>
</body>
</html>

CSS

@import url("https://fonts.googleapis.com/css?family=Signika+Negative:300,400&display=swap");
* {
  box-sizing: border-box;
}

body {
  font-family: "Signika Negative", sans-serif;
  font-weight: 300;
  margin: 0;
}
.v-spacer {
  height: 90vh;
  width: 100%;
  scroll-snap-align: center;
}

svg {
  display: block;
  width: 100vw;
  height: 100vh;
}

#svg2 {
  position: fixed;
}

#circle {
  visibility: hidden;
}

JavaScript

gsap.registerPlugin(ScrollTrigger);

var tl = gsap.timeline();
const hippo = document.getElementById("hippo");

tl.to(
  hippo,
  {
    morphSVG: "#circle",
    duration: 1,
    scrollTrigger: {
      trigger: "#v-spacer-1",
      markers: false,
      scrub: true,
      start: "top top"
    }
  },
  "+=1"
);

后续React版本尝试(菱形→碗形→缩放消失)

进度记录

  • 2025年2月12日:添加三步变形逻辑,但圆形到方形的过渡效果怪异,侧边变化突兀
  • 2025年2月14日:调整为菱形→碗形→缩放消失的流程,但出现底部间隙、变形对齐问题,且无法控制第三步动画的触发时机

React组件代码

'use client';

import React, { useEffect, useRef } from 'react';
import Navigation from "../components/Navigation";
import { gsap } from "gsap-trial";
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { MorphSVGPlugin } from "gsap-trial/MorphSVGPlugin";
import Rotate from './Rotate';

import "./svgMorph.scss";

gsap.registerPlugin(MorphSVGPlugin);
gsap.registerPlugin(ScrollTrigger);

const ScrollMorphing = () => {
  // SVG元素引用
  const diamondRef = useRef(null);
  const bowlRef = useRef(null);

  useEffect(() => {
    // 创建滚动触发的时间线
    const tl = gsap.timeline({
      scrollTrigger: {
        trigger: "#v-spacer-1",
        markers: true,
        scrub: true,
        start: "top top",
        end: "bottom top",
      }
    });

    // 第一步:菱形→碗形变形
    tl.fromTo(diamondRef.current, {
      morphSVG: "#diamond",
      scale: 1,
    }, {
      morphSVG: "#bowl",
      duration: 1
    });

    // 第二步:碗形缩放消失(与变形同步开始)
    tl.fromTo(bowlRef.current, {
      scale: 1,
      opacity: 1,
    }, {
      scale: 2,
      opacity: 0,
      duration: 2,
      ease: "power2.out",
    }, "<");

  }, []);

  return (
    <div>
      <Navigation />
      <div className="h-[100vh] bg-pink-400">
        ScrollMorphing
        <div className="h-[700vh] w-screen overflow-x-hidden">
          <div id="svg-wrapper" className="h-[100vh] w-screen relative m-0 p-0">
            <svg
              version="1.1"
              id="svg-element"
              xmlns="http://www.w3.org/2000/svg"
              xmlnsXlink="http://www.w3.org/1999/xlink"
              viewBox="0 0 1920 1080"
              preserveAspectRatio="none"
              className="w-full h-full absolute top-0 left-0"
            >
              <path
                ref={diamondRef}
                id="diamond"
                className="fill-gray-200"
                d="M960 995 C1280 746.66 1600 498.33 1920 250 1920 517.66 1920 785.33 1920 1053 1280 1053 640 1053 0 1053 0 785.33 0 517.66 0 250 320 498.33 640 746.66 960 995"
              />
              <path
                ref={bowlRef}
                id="bowl"
                className="fill-gray-400 opacity-0"
                d="M960.274 970.219C1498.9 970.219 1935.55 583.629 1935.55 45V1370.66H-15V45C-15 583.629 421.645 970.219 960.274 970.219Z"
                style={{ visibility: "hidden" }}
              />
            </svg>

            <div id="v-spacer-1" className="w-screen h-screen absolute top-[100vh]"></div>
            <div id="v-spacer-2" className="w-screen h-screen absolute top-[200vh]"></div>
            <div id="v-spacer-3" className="w-screen h-screen absolute top-[300vh]"></div>

            <Rotate />
          </div>
        </div>
      </div>
    </div>
  );
};

export default ScrollMorphing;

备注:内容来源于stack exchange,提问作者The Old County

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 09:43:05