我目前正在尝试生成一个SVG路径,表示符合网页宽度的正弦波。
我正在使用的算法是在绘制正弦波的两点之间画一条小线。
算法:
for(var i = 0; i < options.w; i++) {
var operator = ' M ';
d += operator + ((i - 1) * rarity + origin.x) + ', ';
d += (Math.sin(freq * (i - 1 + phase)) * amplitude + origin.y);
if(operator !== ' L ') { operator = ' L '; }
d += ' L ' + (i * rarity + origin.x) + ', ';
d += (Math.sin(freq * (i + phase)) * amplitude + origin.y);
}
为svg生成路径:
M 9, 82.66854866662797 L 10, 102.5192336707523
M 10, 102.5192336707523 L 11, 121.18508371540987
M 11, 121.18508371540987 L 12, 129.88725786264592
M 12, 129.88725786264592 L 13, 124.53298763579338
M 13, 124.53298763579338 L 14, 107.64046998532105
M 14, 107.64046998532105 L 15, 87.15451991511547
M 15, 87.15451991511547 L 16, 72.70999984499424
M 16, 72.70999984499424 L 17, 71.10039326578718
M 17, 71.10039326578718 L 18, 83.08272330249196
M 18, 83.08272330249196 L 19, 103.02151290977501
事情是,在窦的末端,我想绘制一条线来关闭路径的其余部分(使用Z)
对不起我的绘画技巧! :d 关闭路径并链接路径的原因是能够使用背景或渐变填充此路径
我发现我可以在一条链接
的单一路径中表示正弦波M0 50 C 40 10, 60 10, 100 50 C 140 90, 160 90, 200 50 Z
看起来像这样:
但问题是我正在使用的算法让我使用正弦函数,这样我就可以设置这个波浪的动画(这是我需要的东西),我不知道如何动画正弦波的表示。
总而言之,您是否可以帮我找到一种方法来链接实际算法绘制的所有线条?或者一种动画另一种表现形式来绘制波浪而不关心窦的方法。
提前感谢您的帮助!
答案 0 :(得分:1)
以下是横跨svg宽度的正弦波示例。它通过参数方程创建折线。可以通过调整幅度和/或相位角来进行动画。
编辑 - 将动画添加到相角。
<!DOCTYPE HTML>
<html>
<head>
<title>Sine Wave</title>
</head>
<body onload=amplitudeSelected() >
<div style=background:gainsboro;width:400px;height:400px;>
<svg id="mySVG" width="400" height="400">
<polyline id="sineWave" stroke="black" stroke-width="3" fill="blue" ></polyline>
</svg>
</div>
Amplitide:<select id="amplitudeSelect" onChange=amplitudeSelected() >
<option selected>10</option>
<option>20</option>
<option>30</option>
<option>40</option>
<option>50</option>
<option>60</option>
<option>70</option>
<option>80</option>
<option>90</option>
<option>100</option>
</select>
<button onClick=animatePhaseAngle();this.disabled=true >Animate Phase Angle</button>
<script>
//---onload & select---
function amplitudeSelected()
{
var startPoint=[0,400]
var endPoint=[400,400]
var originX=0
var originY=200
var width=400
var amplitude=+amplitudeSelect.options[amplitudeSelect.selectedIndex].text
var pointSpacing=1
var angularFrequency=.02
var phaseAngle=0
var origin = { //origin of axes
x: originX,
y: originY
}
var points=[]
points.push(startPoint)
var x,y
for (var i = 0; i < width/pointSpacing; i++)
{
x= i * pointSpacing + origin.x
y= Math.sin(angularFrequency*(i + phaseAngle)) * amplitude + origin.y
points.push([x,y])
}
points.push(endPoint)
sineWave.setAttribute("points",points.join(" "))
}
//---buton---
function animatePhaseAngle()
{
setInterval(animate,20)
var seg=.5
var cntr=0
var cntrAmp=0
var startPoint=[0,400]
var endPoint=[400,400]
var originX=0
var originY=200
var origin = { //origin of axes
x: originX,
y: originY
}
var width=400
var pointSpacing=1
var angularFrequency=.02
setInterval(animate,10)
function animate()
{
phaseAngle=seg*cntr++
var amplitude=+amplitudeSelect.options[amplitudeSelect.selectedIndex].text
var points=[]
points.push(startPoint)
var x,y
for (var i = 0; i < width/pointSpacing; i++)
{
x= i * pointSpacing + origin.x
y= Math.sin(angularFrequency*(i + phaseAngle)) * amplitude + origin.y
points.push([x,y])
}
points.push(endPoint)
sineWave.setAttribute("points",points.join(" "))
}
}
</script>
</body>
</html>
&#13;
答案 1 :(得分:1)
您可以通过将路径设为两个波长的宽度,然后向左或向右移动来为正弦波设置动画。
<svg width="200" height="100" viewBox="0 0 200 100">
<defs>
<path id="double-wave"
d="M0 50
C 40 10, 60 10, 100 50 C 140 90, 160 90, 200 50
C 240 10, 260 10, 300 50 C 340 90, 360 90, 400 50
L 400 100 L 0 100 Z" />
</defs>
<use xlink:href="#double-wave" x="0" y="0">
<animate attributeName="x" from="0" to="-200" dur="3s"
repeatCount="indefinite"/>
</use>
</svg>
我在这里设置了x
<use>
属性的动画,因为IMO更明显的是发生了什么。
我们正在做的是为我们的双波长路径渲染的位置设置动画。一旦它移动了一个波长的距离,它就会跳回原来的位置并重复。效果是无缝的,因为两个波形是相同的。其余的波浪远离SVG的边缘。
如果你想看看幕后的行为,我们可以让SVG更宽,这样你就可以看到原始SVG左侧和右侧的情况。
<svg width="400" height="100" viewBox="-200 0 600 100">
<defs>
<path id="double-wave"
d="M0 50
C 40 10, 60 10, 100 50 C 140 90, 160 90, 200 50
C 240 10, 260 10, 300 50 C 340 90, 360 90, 400 50
L 400 100 L 0 100 Z" />
</defs>
<use xlink:href="#double-wave" x="0" y="0">
<animate attributeName="x" from="0" to="-200" dur="3s"
repeatCount="indefinite"/>
</use>
<rect width="200" height="100" fill="none" stroke="red" stroke-width="2"/>
</svg>