简体   繁体   中英

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

I am trying to write a javascript loader with svg. 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. 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.

Second approach was this script:

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

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/

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/ ? ;)

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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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