javascript 如何用 SVG (+JS) 绘制正弦波?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13932704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to draw sine waves with SVG (+JS)?
提问by Sk8erPeter
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... :)
在 SVG 中绘制正弦波的最简单解决方案是什么?我想应该使用 JavaScript 在一个简单的循环中重复正弦波... :)
Here are the X-Y coordinates as a good start... :)
这是 XY 坐标作为一个好的开始... :)
http://jsbin.com/adaxuy/1/edit
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>
采纳答案by Asad Saeeduddin
Here is a proof of concept that adds multiple line
elements to the SVG element:
这是line
向 SVG 元素添加多个元素的概念证明:
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>
回答by Thomas W
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)
(请参阅评论中 NominalAnimal 的解释)
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)2)/6 (6?(3/2π?3)2)/6
1 1
π/2 1
(见推导)
回答by broofa
The following will add a one-cycle sine wave to your SVG graph:
以下将向您的 SVG 图形添加一个单周期正弦波:
var XMAX = 500;
var YMAX = 500;
// Create path instructions
var path = [];
for (var x = 0; x <= XMAX; x++) {
var angle = (x / XMAX) * Math.PI * 2; // angle = 0 -> 2π
var y = Math.sin(angle) * (YMAX / 2) + (YMAX / 2);
// M = move to, L = line to
path.push((x == 0 ? 'M' : 'L') + x + ',' + y);
}
// Create PATH element
var pathEl = document.createElementNS("http://www.w3.org/2000/svg", "path");
pathEl.setAttribute('d', path.join(' ') );
pathEl.style.stroke = 'blue';
pathEl.style.fill = 'none';
// Add it to svg element
document.querySelector('svg').appendChild(pathEl);
? ?
Here's the jsfiddle you can run.
This uses a PATH elementmade up of 'lineto' (straight line) commands. This works because, not surprisingly, it contains many (500) small line segments. You could simplify the path to have fewer points by using bezier curves to draw the segments, but this complicates the code. And you asked for simple. :)
这使用由“lineto”(直线)命令组成的PATH 元素。这是有效的,因为毫不奇怪,它包含许多 (500) 条小线段。您可以通过使用贝塞尔曲线绘制线段来简化路径以减少点,但这会使代码复杂化。而你要求的很简单。:)
回答by sffc
In case it is useful to anybody: Here is a one-liner SVG that closely approximates half of a sine wave using a cubic bezier approximation.
如果它对任何人有用:这是一个单线 SVG,它使用三次贝塞尔近似近似近似正弦波的一半。
<svg width="100px" height="100px" viewBox="0 0 100 100">
<path stroke="#000000" fill="none" d="M0,0 C36.42,0,63.58,100,100,100" />
</svg>
I fitted the parameter 36.42
by minimizing the sum-squared (l2) distance between the bezier curve and the true cosine curve. https://octave-online.net/bucket~AN33qHTHk7eARgoSe7xpYg
我36.42
通过最小化贝塞尔曲线和真余弦曲线之间的平方和 (l2) 距离来拟合参数。https://octave-online.net/bucket~AN33qHTHk7eARgoSe7xpYg
My answer is based in part on How to approximate a half-cosine curve with bezier paths in SVG?
我的答案部分基于如何在 SVG 中使用贝塞尔路径近似半余弦曲线?
回答by feeela
Loop over the X axis and for each iteration compute the Y position using a sine function on the current X value.
在 X 轴上循环并为每次迭代使用当前 X 值的正弦函数计算 Y 位置。