生成一个段的

时间:2017-03-22 19:27:46

标签: javascript css algorithm svg

我目前正在尝试生成一个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)

Waves path closed

对不起我的绘画技巧! :d 关闭路径并链接路径的原因是能够使用背景或渐变填充此路径

我发现我可以在一条链接

的单一路径中表示正弦波
M0 50  C 40 10, 60 10, 100 50 C 140 90, 160 90, 200 50 Z

看起来像这样:

Sinus waves estimated

但问题是我正在使用的算法让我使用正弦函数,这样我就可以设置这个波浪的动画(这是我需要的东西),我不知道如何动画正弦波的表示。

总而言之,您是否可以帮我找到一种方法来链接实际算法绘制的所有线条?或者一种动画另一种表现形式来绘制波浪而不关心窦的方法。

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

以下是横跨svg宽度的正弦波示例。它通过参数方程创建折线。可以通过调整幅度和/或相位角来进行动画。

编辑 - 将动画添加到相角。

&#13;
&#13;
<!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;
&#13;
&#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>