基于GSAP实现滚动触发的SVG多图形平滑变形(三角形→圆形→方形)问题求助
基于GSAP实现滚动触发的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
相关产品推荐
相关产品推荐

