英文:
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 feTurbulence
filter 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('#fltOne')
.transition()
.duration(time)
.ease(d3.easeLinear)
.tween('x', function() {
return function(t) {
x = x + step * direction;
if (x >= upper || x <= lower) {
direction *= -1; // Reverse direction at upper and lower bounds
}
d3.select(this).attr('baseFrequency', x);
};
}).on('end', animateBaseFrequency);
}
animateBaseFrequency();
<!-- language: lang-html -->
<!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(&quot;#filt&quot;);"></rect>
</svg>
</div>
<!--d3 script-->
<script src="prod.js" defer></script>
</body>
</html>
<!-- end snippet -->
答案1
得分: 4
- 在湍流中使用
stitchTiles="stitch"
,以产生一个无缝重复的瓷砖 - 使用双倍宽度的
<feTile>
重复湍流瓷砖两次 - 对该图案的
x
位置进行动画处理,使其在湍流瓷砖的宽度上重复 - 将结果用作位移图的输入
请注意,在应用偏移之前,整个滤镜必须具有足够的宽度来容纳完整的重复瓷砖,否则 <feTile>
将在滤镜区域的边界处被截断。
在图片中,绿色虚线是应用滤镜的图像范围。蓝色线是滤镜效果区域。每个滤镜效果都被裁剪到这个矩形内。其大小取决于属性 filterUnits, x, y, width, height
的值。在下面的行中,灰色显示了默认值。
每个滤镜原语的大小,即滤镜原语子区域,由其自己的 x, y, width, height
值给出。但这些值并不是像滤镜效果区域那样以图像大小的倍数解释的,而是在图像的坐标系中,由属性 filterPrimitiveUnits="userSpaceOnUse"
规定。
瓷砖图案填充了滤镜效果区域。如果它更小,它将在其边界处被截断,无论 feTile
原语的大小如何。
最后一行图片显示了动画的各个阶段。请注意瓷砖图案是如何在左侧被截断的。
英文:
How about this:
- use
stitchTiles="stitch"
on the turbulence so that a seamlessly repeatable tile is produced - repeat the tubulence tile two times with a double-wide
<feTile>
- animate the
x
position of that pattern repeatedly for the width of the turbulence tile - use the result as input for the displacement map
Note that the whole filter must have sufficient width to contain the complete repeated tile before the offset is applied, otherwise <feTile>
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="userSpaceOnUse"
.
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 -->
<svg viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg">
<defs id="pattern">
<filter id="filt" width="2">
<feTurbulence numOctaves="1" seed="1" baseFrequency="0.008"
stitchTiles="stitch"
id="fltOne" width="400" height="400">
</feTurbulence>
<feTile width="800" height="400">
</feTile>
<feOffset result="TURBULENCE" dx="0">
<animate attributeName="dx" from="-400" to="0"
begin="0s" dur="2s" repeatCount="indefinite" />
</feOffset>
<feDisplacementMap in="SourceGraphic" in2="TURBULENCE" scale="30" result="dist" id="fltTwo">
</feDisplacementMap>
</filter>
</defs>
<image xlink:href="https://raw.githubusercontent.com/d3/d3-logo/master/d3.svg" x="100" y="100" width="400" height="300" style="filter: url(#filt);" />
</svg>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论