如何实现滚动时SVG Logo动态切换?(仿Awwwards网站效果)
Hey there! Since you already know your way around CSS, JS, and SVG animations, let’s dive into how to hook those animations up to scroll behavior—starting with a pure CSS approach (when possible) and then a lean JS solution for broader compatibility or more control.
If you don’t need to support older browsers (Chrome 115+, Firefox 117+, Safari 16.4+), pure CSS scroll-driven animations are your best bet—zero JS, great performance, and clean code.
How to Modify Your SVG
First, tweak your SVG to work with CSS animations:
- Remove any internal
<animate>or<animateTransform>elements (we’ll handle animation in CSS instead). - Add class names to the SVG elements you want to animate (e.g., paths, circles) so CSS can target them easily.
- For path-based animations (like stroke drawing), calculate the total length of your path first: open your browser’s dev tools, select the path, and run
$0.getTotalLength()in the console to get the exact value.
Example Code
<!-- Modified SVG: No internal animations, added class to path --> <svg class="logo-svg" viewBox="0 0 200 200"> <path class="logo-stroke" d="M10,10 L190,10 L190,190 L10,190 Z" fill="none" stroke="#2d3748" stroke-width="2"/> </svg>
.logo-svg { position: fixed; top: 2rem; left: 2rem; width: 6rem; height: 6rem; } .logo-stroke { stroke-dasharray: 720; /* Use the total length you calculated */ stroke-dashoffset: 720; /* Bind animation to page scroll */ animation: draw-logo linear; animation-timeline: scroll(); /* Ties animation to overall page scroll */ animation-range: 0 100vh; /* Animation completes as you scroll from 0 to 100% viewport height */ } @keyframes draw-logo { to { stroke-dashoffset: 0; } }
Key Notes
- Use
animation-rangeto define exactly when the animation starts and ends (e.g.,20vh 80vhto only animate between 20% and 80% of the page). - You can animate other properties too—like
scale,rotate, oropacity—by adding them to the@keyframesrule.
If you need to support older browsers or want fine-grained control over how scroll maps to animation progress, a tiny JS snippet is all you need. We’ll use requestAnimationFrame to keep performance smooth (no janky scroll events).
How to Modify Your SVG
Same as the CSS approach:
- Remove internal animation elements.
- Add class names to targetable elements.
- Pre-calculate path lengths if using stroke animations.
Example Code
<svg class="logo-svg" viewBox="0 0 200 200"> <path class="logo-stroke" d="M10,10 L190,10 L190,190 L10,190 Z" fill="none" stroke="#2d3748" stroke-width="2"/> <circle class="logo-circle" cx="100" cy="100" r="30" fill="#4a5568" opacity="0"/> </svg>
.logo-svg { position: fixed; top: 2rem; left: 2rem; width: 6rem; height: 6rem; } .logo-stroke { stroke-dasharray: 720; stroke-dashoffset: 720; } .logo-circle { transform: scale(0); transition: transform 0.1s ease; /* Smooth out updates */ }
// Super lean JS (≈20 lines) const logoStroke = document.querySelector('.logo-stroke'); const logoCircle = document.querySelector('.logo-circle'); const strokeLength = logoStroke.getTotalLength(); let lastProgress = 0; // Update animation on scroll (optimized with requestAnimationFrame) const updateScrollAnimation = () => { const scrollTop = window.scrollY; const maxScroll = document.body.scrollHeight - window.innerHeight; const scrollProgress = maxScroll > 0 ? scrollTop / maxScroll : 0; // Only update if progress changed (avoids unnecessary reflows) if (scrollProgress !== lastProgress) { // Update stroke animation logoStroke.style.strokeDashoffset = strokeLength * (1 - scrollProgress); // Update circle animation (fade in + scale up as scroll progresses) logoCircle.style.opacity = scrollProgress; logoCircle.style.transform = `scale(${scrollProgress})`; lastProgress = scrollProgress; } requestAnimationFrame(updateScrollAnimation); }; // Kick off the animation loop updateScrollAnimation();
Key Notes
- This approach lets you map scroll progress to multiple SVG properties at once (e.g., stroke drawing + circle scaling + opacity fade).
- Adjust the math to tweak animation behavior: for example, use
scrollProgress * 2to make the animation finish halfway through scrolling, or1 - scrollProgressto reverse the animation as you scroll down. - If you prefer to use SVG’s internal animations, you can control them via JS too: get the
<animate>element and set itscurrentTimebased on scroll progress (e.g.,animElement.currentTime = scrollProgress * animElement.getDur()).
内容的提问来源于stack exchange,提问作者Reza Rayatpishe

