简体   繁体   English

Javascript + SVG,在两个给定点之间绘制窦(波浪)线

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

I am trying to write a javascript loader with svg. 我试图用svg编写一个javascript加载器。 Idea is that it is circle that is being filled from bottom to top equally on both sides and the top line of loader is a sinus wave continuesly moving from left to right. 想法是,这是一个圆形,从底部到顶部在两侧均等地填充,并且装载机的顶线是从左向右连续移动的正弦波。

I was able to create an arc for loader based on percentage like this: 我能够基于这样的百分比为装载机创建一个弧:

    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>';
    };

Above code is essentially creating "U" shaped arc that is becoming full circle if You pass 100% load as parameter. 上面的代码实质上是创建“ U”形弧,如果您将100%负载作为参数传递,则该弧将变为完整的圆。 The problem now is with top line that needs to be a animated wave. 现在的问题是顶线需要成为动画。 I tried to do it with quadratic bezier curve but i had problems calculating the points inside. 我试图用二次贝塞尔曲线来做,但是在计算内部点时遇到了问题。 I only know start(x,y) and end(x,y) points, dont know how to calculate other ones. 我只知道start(x,y)和end(x,y)点,不知道如何计算其他点。

Second approach was this script: 第二种方法是此脚本:

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

but its not working for me because i cannot specify start and end points and sine line is always drawed in wrong place. 但它对我不起作用,因为我无法指定起点和终点,并且正弦线始终绘制在错误的位置。

The final goal is to fill entire shape ("U" arc and closing sine line) with some color, so the sine line must conitnue the arc path from above code 最终目标是用某种颜色填充整个形状(“ U”形弧和正弦闭合线),因此正弦线必须从上述代码连接弧路径

d="M ' + start.x + ' ' + start.y + ' A ' + r + ' ' + r + ' 0 ' + sw + ' 0 ' + end.x + ' ' + end.y + ' //sine line continue here . d="M ' + start.x + ' ' + start.y + ' A ' + r + ' ' + r + ' 0 ' + sw + ' 0 ' + end.x + ' ' + end.y + ' //sine line continue here

This is a full code of approach (not working, just idea): 这是完整的方法代码(不起作用,仅是想法):

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

does anyone have an idea how to create that sine line from point A to point B, that can be animated like in this example https://jsfiddle.net/assa0r70/7/ ? 有谁知道如何创建从点A到点B的正弦线,该线可以像本例https://jsfiddle.net/assa0r70/7/那样进行动画处理? ;) ;)

This example animates a polyline, built via a parametric equation for a sine wave. 本示例对通过正弦波的参数方程构建的折线进行动画处理。 Also it uses Paul Lebeau's suggestion of mask circle. 它还使用了保罗·勒博的面具圈的建议。 It will move up/down the circle based on percentage selection. 它将根据百分比选择上下移动圆。

 <!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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM