Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw sine waves with SVG (+JS)?

Tags:

What would be the simplest solution to draw sine waves in SVG? I guess sine waves should be repeated in a simple loop with JavaScript... :)

Here are the X-Y coordinates as a good start... :)

http://jsbin.com/adaxuy/1/edit

<svg>   <line x1="0" y1="250" x2="500" y2="250"         style="stroke:black;stroke-width:1"/>   <line x1="250" y1="0" x2="250" y2="500"         style="stroke:black;stroke-width:1"/> </svg> 
like image 676
Sk8erPeter Avatar asked Dec 18 '12 12:12

Sk8erPeter


2 Answers

An alternative to straight-line approximations would be a Bézier approximation. A pretty good approximation of the first quarter of one period is a cubic Bézier curve with the following control points:

 0   0 1/2 1/2  1   1 π/2  1 

Edit: Even more exact approximations are possible with the following control points:

0                    0 0.512286623256592433 0.512286623256592433 1.002313685767898599 1 1.570796326794896619 1 

(See NominalAnimal's explanations in the comments)

Demo comparing line elements (gray) and "good" Bézier (red) and "better" Bézier (green).

An approximation that exactly interpolates the slope and curvature in the spline's endpoints is

       0                0  (6−(3/2π−3)²)/6  (6−(3/2π−3)²)/6        1                1       π/2               1 

(See derivation)

like image 72
Thomas W Avatar answered Sep 28 '22 10:09

Thomas W


Here is a proof of concept that adds multiple line elements to the SVG element:

var svg = document.getElementById('sine_wave').children[0];  var origin = { //origin of axes      x: 100,      y: 100  };  var amplitude = 10; // wave amplitude  var rarity = 1; // point spacing  var freq = 0.1; // angular frequency  var phase = 0; // phase angle    for (var i = -100; i < 1000; i++) {      var line = document.createElementNS("http://www.w3.org/2000/svg", "line");        line.setAttribute('x1', (i - 1) * rarity + origin.x);      line.setAttribute('y1', Math.sin(freq*(i - 1 + phase)) * amplitude + origin.y);        line.setAttribute('x2', i * rarity + origin.x);      line.setAttribute('y2', Math.sin(freq*(i + phase)) * amplitude + origin.y);        line.setAttribute('style', "stroke:black;stroke-width:1");        svg.appendChild(line);  }
html, body, div{      height:100%;  }
<div id="sine_wave">      <svg width="1000" height="1000">      <line x1="100" y1="0" x2="100" y2="200"            style="stroke:black;stroke-width:1"/>      <line x1="0" y1="100" x2="1000" y2="100"            style="stroke:black;stroke-width:1"/>    </svg>    </div>
like image 32
Asad Saeeduddin Avatar answered Sep 28 '22 09:09

Asad Saeeduddin