SVG 中的无缝波浪效果

huangapple go评论54阅读模式
英文:

Seamless Waving Effect in svg

问题

以下是翻译好的部分:

有没有一种方法可以实现整个SVG的完美无缝波动效果?我尝试通过动画化feTurbulence滤镜的baseFrequency来解决这个问题,但它没有给我想要的效果。

const lower = 0;
const upper = 0.008;
const step = 0.0001;
const time = 5000;

function animateBaseFrequency() {
    let direction = 1; // 1表示增加,-1表示减少
    let x = lower;

    d3.select('#fltOne')
        .transition()
        .duration(time)
        .ease(d3.easeLinear)
        .tween('x', function() {
            return function(t) {
                x = x + step * direction;
                if (x >= upper || x <= lower) {
                    direction *= -1; // 在上下界处反转方向
                }

                d3.select(this).attr('baseFrequency', x);
            };
        }).on('end', animateBaseFrequency);
}

animateBaseFrequency();
<!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>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<body>
    <link rel="stylesheet" href="style.css">
    <div id="container" class="svg-container">
        <svg viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg">
            <defs id="pattern">
                <pattern id="af" width="100%" height="100%" patternContentUnits="objectBoundingBox">
                    <image xlink:href="https://raw.githubusercontent.com/d3/d3-logo/master/d3.svg"
                        preserveAspectRatio="xMidYMid meet" width="1" height="1"></image>
                </pattern>
                <pattern patternContentUnits="userSpaceOnUse" id="main">
                    <rect class="patRect" width="400" height="300" fill="url(#af)"></rect>
                </pattern>
                <filter id="filt">
                    <feTurbulence result="TURBULENCE" numOctaves="1" seed="1" baseFrequency="0" stitchTiles="noStitch"
                        id="fltOne"></feTurbulence>
                    <feDisplacementMap in="SourceGraphic" in2="TURBULENCE" scale="30" result="dist" id="fltTwo">
                    </feDisplacementMap>
                </filter>
            </defs>
            <rect class="rectOne" x="100" y="100" width="400" height="300" fill="url(#af)"
                style="filter: url('#filt');"></rect>
        </svg>
    </div>
    <!--d3 script-->
    <script src="prod.js" defer></script>
</body>

</html>

请注意,代码部分未被翻译。

英文:

Is there a way to achieve a perfect seamless waving effect for the whole of a svg. I tried approaching the problem by animating the baseFrequency of feTurbulencefilter but it is not giving me what I need.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const lower = 0;
const upper = 0.008;
const step = 0.0001;
const time = 5000;
function animateBaseFrequency() {
let direction = 1; // 1 for incrementing, -1 for decrementing
let x = lower;
d3.select(&#39;#fltOne&#39;)
.transition()
.duration(time)
.ease(d3.easeLinear)
.tween(&#39;x&#39;, function() {
return function(t) {
x = x + step * direction;
if (x &gt;= upper || x &lt;= lower) {
direction *= -1; // Reverse direction at upper and lower bounds
}
d3.select(this).attr(&#39;baseFrequency&#39;, x);
};
}).on(&#39;end&#39;, animateBaseFrequency);
}
animateBaseFrequency();

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
&lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;https://d3js.org/d3.v7.min.js&quot;&gt;&lt;/script&gt;
&lt;body&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;
&lt;div id=&quot;container&quot; class=&quot;svg-container&quot;&gt;
&lt;svg viewBox=&quot;0 0 1280 720&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
&lt;defs id=&quot;pattern&quot;&gt;
&lt;pattern id=&quot;af&quot; width=&quot;100%&quot; height=&quot;100%&quot; patternContentUnits=&quot;objectBoundingBox&quot;&gt;
&lt;image xlink:href=&quot;https://raw.githubusercontent.com/d3/d3-logo/master/d3.svg&quot;
preserveAspectRatio=&quot;xMidYMid meet&quot; width=&quot;1&quot; height=&quot;1&quot;&gt;&lt;/image&gt;
&lt;/pattern&gt;
&lt;pattern patternContentUnits=&quot;userSpaceOnUse&quot; id=&quot;main&quot;&gt;
&lt;rect class=&quot;patRect&quot; width=&quot;400&quot; height=&quot;300&quot; fill=&quot;url(#af)&quot;&gt;&lt;/rect&gt;
&lt;/pattern&gt;
&lt;filter id=&quot;filt&quot;&gt;
&lt;feTurbulence result=&quot;TURBULENCE&quot; numOctaves=&quot;1&quot; seed=&quot;1&quot; baseFrequency=&quot;0&quot; stitchTiles=&quot;noStitch&quot;
id=&quot;fltOne&quot;&gt;&lt;/feTurbulence&gt;
&lt;feDisplacementMap in=&quot;SourceGraphic&quot; in2=&quot;TURBULENCE&quot; scale=&quot;30&quot; result=&quot;dist&quot; id=&quot;fltTwo&quot;&gt;
&lt;/feDisplacementMap&gt;
&lt;/filter&gt;
&lt;/defs&gt;
&lt;rect class=&quot;rectOne&quot; x=&quot;100&quot; y=&quot;100&quot; width=&quot;400&quot; height=&quot;300&quot; fill=&quot;url(#af)&quot;
style=&quot;filter: url(&amp;quot;#filt&amp;quot;);&quot;&gt;&lt;/rect&gt;
&lt;/svg&gt;
&lt;/div&gt;
&lt;!--d3 script--&gt;
&lt;script src=&quot;prod.js&quot; defer&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- end snippet -->

答案1

得分: 4

  • 在湍流中使用 stitchTiles=&quot;stitch&quot;,以产生一个无缝重复的瓷砖
  • 使用双倍宽度的 &lt;feTile&gt; 重复湍流瓷砖两次
  • 对该图案的 x 位置进行动画处理,使其在湍流瓷砖的宽度上重复
  • 将结果用作位移图的输入

请注意,在应用偏移之前,整个滤镜必须具有足够的宽度来容纳完整的重复瓷砖,否则 &lt;feTile&gt; 将在滤镜区域的边界处被截断。

在图片中,绿色虚线是应用滤镜的图像范围。蓝色线是滤镜效果区域。每个滤镜效果都被裁剪到这个矩形内。其大小取决于属性 filterUnits, x, y, width, height 的值。在下面的行中,灰色显示了默认值。

每个滤镜原语的大小,即滤镜原语子区域,由其自己的 x, y, width, height 值给出。但这些值并不是像滤镜效果区域那样以图像大小的倍数解释的,而是在图像的坐标系中,由属性 filterPrimitiveUnits=&quot;userSpaceOnUse&quot; 规定。

瓷砖图案填充了滤镜效果区域。如果它更小,它将在其边界处被截断,无论 feTile 原语的大小如何。

最后一行图片显示了动画的各个阶段。请注意瓷砖图案是如何在左侧被截断的。

英文:

How about this:

  • use stitchTiles=&quot;stitch&quot; on the turbulence so that a seamlessly repeatable tile is produced
  • repeat the tubulence tile two times with a double-wide &lt;feTile&gt;
  • animate the x position of that pattern repeatedly for the width of the turbulence tile
  • use the result as input for the displacement map

SVG 中的无缝波浪效果

Note that the whole filter must have sufficient width to contain the complete repeated tile before the offset is applied, otherwise &lt;feTile&gt; will be cut of at the border of the filter region.

In the picture, the green dashed line is the extent of the image the filter is applied to. The blue line is the filter effect region. Every filter effect is clipped to this rectangle. Its size depends on the values of the attributes filterUnits, x, y, width, height. In the line below, default values are shown in grey.

The size of each filter primitive, the filter primitive subregion is given with its own x, y, width, height values. But the values are not interpreted in multiples of the image size, like the filter effect region, but in the coordinate system of the image, as prescribed by the attribute filterPrimitiveUnits=&quot;userSpaceOnUse&quot;.

The tiled pattern fills the filter effects region. Would that be smaller, it would be cut of at its border, regardless what the size of the feTile primitive says.

The last line of pictures shows stages of the animation. Note how the tiled pattern is cut of at the left side.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;svg viewBox=&quot;0 0 1280 720&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
&lt;defs id=&quot;pattern&quot;&gt;
&lt;filter id=&quot;filt&quot; width=&quot;2&quot;&gt;
&lt;feTurbulence numOctaves=&quot;1&quot; seed=&quot;1&quot; baseFrequency=&quot;0.008&quot;
stitchTiles=&quot;stitch&quot;
id=&quot;fltOne&quot; width=&quot;400&quot; height=&quot;400&quot;&gt;
&lt;/feTurbulence&gt;
&lt;feTile width=&quot;800&quot; height=&quot;400&quot;&gt;
&lt;/feTile&gt;
&lt;feOffset result=&quot;TURBULENCE&quot; dx=&quot;0&quot;&gt;
&lt;animate attributeName=&quot;dx&quot; from=&quot;-400&quot; to=&quot;0&quot;
begin=&quot;0s&quot; dur=&quot;2s&quot; repeatCount=&quot;indefinite&quot; /&gt;
&lt;/feOffset&gt;
&lt;feDisplacementMap in=&quot;SourceGraphic&quot; in2=&quot;TURBULENCE&quot; scale=&quot;30&quot; result=&quot;dist&quot; id=&quot;fltTwo&quot;&gt;
&lt;/feDisplacementMap&gt;
&lt;/filter&gt;
&lt;/defs&gt;
&lt;image xlink:href=&quot;https://raw.githubusercontent.com/d3/d3-logo/master/d3.svg&quot; x=&quot;100&quot; y=&quot;100&quot; width=&quot;400&quot; height=&quot;300&quot; style=&quot;filter: url(#filt);&quot; /&gt;
&lt;/svg&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年7月28日 00:40:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76781834.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定