我正在尝试用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>';
};
如果您将100%负载作为参数传递,则上面的代码实际上是创建“U”形弧,该弧变为整圆。现在的问题是顶线需要是一个动画波。我尝试用二次贝塞尔曲线做到这一点,但我在计算里面的点时遇到了问题。我只知道start(x,y)和end(x,y)点,不知道如何计算其他点。
第二种方法是这个脚本:
https://jsfiddle.net/assa0r70/7/
但它对我不起作用,因为我无法指定起点和终点,而且正弦线总是在错误的位置绘制。
最终目标是用一些颜色填充整个形状(“U”弧和关闭正弦线),因此正弦线必须从上面的代码中包含弧形路径
d="M ' + start.x + ' ' + start.y + ' A ' + r + ' ' + r + ' 0 ' + sw + ' 0 ' + end.x + ' ' + end.y + ' //sine line continue here
。
这是一个完整的方法代码(不工作,只是想法):
https://jsfiddle.net/9hnuzp1d/11/
有没有人知道如何创建从A点到B点的正弦线,这可以像本例https://jsfiddle.net/assa0r70/7/一样动画? ;)
答案 0 :(得分:2)
此示例为通过正弦波的参数方程构建的折线设置动画。它还使用了Paul Lebeau关于面具圈的建议。它将根据百分比选择向上/向下移动。
<!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>