如何实现SVG的完美无缝波浪效果?
实现SVG无缝波浪效果的正确方案
问题分析
你之前通过来回增减feTurbulence的baseFrequency值尝试实现波浪效果,但这种方式只会让波浪缩放,无法形成连续无缝的流动效果;同时stitchTiles="noStitch"的设置也会导致图案边缘出现断裂。
解决方案
要实现完美无缝的波浪流动,核心是让湍流图案平滑滚动而非缩放,同时开启无缝拼接。以下是调整后的实现方案:
优化后的HTML + SVG代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SVG无缝波浪效果</title> <script src="https://d3js.org/d3.v7.min.js"></script> </head> <body> <div id="container" class="svg-container"> <svg viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg"> <defs> <pattern id="af" width="100%" height="100%" patternContentUnits="objectBoundingBox"> <image href="https://raw.githubusercontent.com/d3/d3-logo/master/d3.svg" preserveAspectRatio="xMidYMid meet" width="1" height="1"></image> </pattern> <filter id="filt"> <!-- 开启无缝拼接,固定x方向频率,动画y分量实现滚动 --> <feTurbulence result="TURBULENCE" numOctaves="1" seed="1" baseFrequency="0.008 0" stitchTiles="stitch" id="fltOne"> <!-- SVG原生动画,让y分量循环变化,实现波浪持续滚动 --> <animate attributeName="baseFrequency" from="0.008 0" to="0.008 0.016" dur="5s" repeatCount="indefinite" /> </feTurbulence> <feDisplacementMap in="SourceGraphic" in2="TURBULENCE" scale="30" /> </filter> </defs> <rect class="rectOne" x="100" y="100" width="400" height="300" fill="url(#af)" style="filter: url(#filt);"></rect> </svg> </div> </body> </html>
关键调整点
- 开启无缝拼接:将
feTurbulence的stitchTiles设为stitch,确保湍流图案边缘完全衔接 - 动画方向而非缩放:固定
baseFrequency的x分量(控制波浪密度),只动画y分量,让湍流图案沿垂直方向平滑滚动,形成连续波浪 - 使用SVG原生动画:相比D3的tween逻辑,SVG原生
animate元素更适合这种循环滚动的场景,代码更简洁且性能更优
若偏好D3实现动画
如果你更习惯用D3控制动画逻辑,可以调整tween函数,只累加baseFrequency的y分量并循环重置:
function animateBaseFrequency() { let y = 0; const frequencyX = 0.008; const step = 0.0001; const time = 5000; d3.select('#fltOne') .transition() .duration(time) .ease(d3.easeLinear) .tween('y', function() { return function(t) { y += step; // 达到阈值后重置,实现循环滚动 if (y >= 0.016) y = 0; d3.select(this).attr('baseFrequency', `${frequencyX} ${y}`); }; }).on('end', animateBaseFrequency); } animateBaseFrequency();
原理说明
feTurbulence生成的Perlin噪声图案中,baseFrequency的两个分量分别控制x、y方向的噪声密度。固定一个分量,动画另一个分量,相当于让整个噪声图案沿对应方向平移;配合stitchTiles="stitch"的无缝拼接设置,就能实现完全连续的波浪流动效果。
内容的提问来源于stack exchange,提问作者smpa01
相关产品推荐
相关产品推荐

