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

如何实现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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 20:59:53