Javascript+svg,在两个给定点之间绘制正弦(波浪)线

Javascript + svg, draw sinus (wave) line between two given points

本文关键字:绘制 之间 波浪 Javascript+svg 两个      更新时间:2023-09-26

我正在尝试用svg编写一个javascript加载程序。我们的想法是,这是一个从下到上在两侧均匀填充的圆圈,装载机的顶部线是一个正弦波,从左到右连续移动。

我能够为加载器创建一个基于百分比的弧线,如下所示:

    var d_arc = function(x, y, r, sa, ea) { // calculate arc path from given parameters
        var start = pfa(x, y, r, ea),
            end = pfa(x, y, r, sa),
            sw = ea - sa <= 180 ? '0' : '1';
        return '<path d="M ' + start.x + ' ' + start.y + ' A ' + r + ' ' + r + ' 0 ' + sw + ' 0 ' + end.x + ' ' + end.y + '" class="path-progress"></path>';
    };

上面的代码本质上是创建一个"U"形的弧,如果你通过100%的负荷作为参数,它将变成一个完整的圆。现在的问题是最上面一行需要一个动画波浪。我试着用二次贝塞尔曲线来做,但我在计算里面的点时遇到了问题。我只知道起点(x,y)和终点(x,y),不知道如何计算其他点。

第二种方法是这个脚本:

https://jsfiddle.net/assa0r70/7/

但这对我来说不起作用,因为我不能指定起点和终点,而且正弦线总是画在错误的地方。

最后的目标是用一些颜色填充整个形状("U"弧和闭合的正弦线),因此正弦线必须与上面代码的弧路径成锥形

CCD_ 1。

这是一个完整的方法代码(不起作用,只是想法):

https://jsfiddle.net/9hnuzp1d/11/

有人知道如何创建从A点到B点的正弦线吗,可以像这个例子中那样设置动画https://jsfiddle.net/assa0r70/7/?)

此示例通过正弦波的参数方程创建多段线动画。此外,它还使用了保罗·勒博关于面具圈的建议。它将根据百分比选择向上/向下移动圆圈。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>Animate Sine Wave</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body onload=animateSineWave() style='font-family:arial'>
<center>
<div style='width:90%;background-color:gainsboro;text-align:justify;padding:10px;border-radius:6px;'>
Animate a sine wave, using parametric equation to build a polyline. Move it up/down circle via Percentage selection.
</div>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400">
    <defs>
        <mask id="circle">
            <circle cx="200" cy="200" r="200" fill="white"/>
        </mask>
    </defs>
     <polyline id=sineWave stroke=blue stroke-width=3  fill="#ccc" stroke="red" mask="url(#circle)" />
    <circle cx="200" cy="200" r="200" fill="none" stroke="red"/>
</svg>
</div>
Percentage:<select id=percentSelect>
<option value=.1 >10%</option>
<option value=.3 >30%</option>
<option value=.5 >50%</option>
<option selected value=.8 >80%</option>
</select>
</center>
<script>
function buildSineWave(amplitude)
{
    //---mask fill bottom of circle
    var startPoint=[0,400]
    var endPoint=[400,400]
    var originX=0
    var percent=parseFloat(percentSelect.options[percentSelect.selectedIndex].value)
    var originY=400*(1-percent)
    var width=400
    var pointSpacing=1
    var angularFrequency=.02
    var phaseAngle=90
    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(" "))
}
function animateSineWave()
{
    var range=60 //--amplitude +/- ---
    var FPS=120  //---frames per second---
    var duration=2000 //---ms, 2 seconds---
    //----core animation function---
		new AnimateJS(
		{
			delay: 1000/FPS,
			duration: duration,
			delta: linear,
			output: function(delta)
			{
                if(delta<=.5)
                var amplitude=range*delta
                else
                var amplitude=60-range*delta
                buildSineWave(amplitude)
                if(progress==1)//---run again---
                    animateSineWave()
			}
		})
}
/*---generalized animate core function
 Inspired by: Ilya Kantor - http://javascript.info/tutorial/animation
*/
var linear=function linear(p){return p}//---linear---
//----Animate Object---
var AnimateJS=function(options){
    this.options=options
	var start = new Date
	var iT = setInterval(
	function(){
		var timePassed = new Date - start
		var progress = timePassed / options.duration
		if (progress > 1) progress = 1
		this.progress=progress
		var delta = options.delta(progress)
		options.output(delta)
		if (progress == 1)clearInterval(iT);
	},options.delay)
}
</script>
</script>
</body>
</html>