简体   繁体   English

动画正弦波,固定起点和终点

[英]Animate sine wave, fixed start and end points

I have a sine wave in my canvas that is animated, swaying left and right. 我的画布上有一个正弦波,它是动画的,左右摇晃。 What I am trying to achieve is that the start and end points stay fixed. 我想要实现的是起点和终点保持不变。 How to achieve that? 怎么实现呢?

Here is the Code Pen 这是Code Pen

 function start() { var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); context.clearRect(0, 0, canvas.width, canvas.height); drawCurves(context, step); step += 5; window.requestAnimationFrame(start); } var step = -4; function drawCurves(ctx, step) { var width = ctx.canvas.width; var height = ctx.canvas.height; ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = "rgb(66,44,255)"; var x = 4; var y = 0; var amplitude = 20; var frequency = 90; while (y < height) { x = width / 2 + amplitude * Math.sin((y + step) / frequency); ctx.lineTo(x, y); y++; } ctx.stroke(); } 
 canvas { background-color: wheat; } 
 <!DOCTYPE html> <html> <head> </head> <body onload="start()"> <canvas id="canvas" width="500" height="2000"></canvas> </body> </html> 

I've changed the size of your canvas because I wanted to be able to see it. 我已经改变了画布的大小,因为我希望能够看到它。 You can change it back to what you need. 您可以将其更改回您需要的内容。

I've done 2 things: 我做了两件事:

  1. The frequency has to be var frequency = height / (2 * Math.PI); 频率必须是var frequency = height / (2 * Math.PI); or var frequency = height / (4 * Math.PI); var frequency = height / (4 * Math.PI); . The divider has to be a multiple of 2 * Math.PI 分隔符必须是2 * Math.PI的倍数

  2. I translate the context the opposite direction the same amount: ctx.translate(-amplitude * Math.sin(step / frequency), 0); 我将相反方向的上下文转换为相同的量: ctx.translate(-amplitude * Math.sin(step / frequency), 0);

If you need a more subtile oscillation play with the amplitude. 如果你需要一个更加微妙的振荡播放振幅。

In my code there is a commented out ctx.closePath() Please uncomment this line to see clearly that the sine-wave stay fixed in the center. 在我的代码中有一个注释掉的ctx.closePath()请取消注释该行以清楚地看到正弦波保持固定在中心。 I hope this is what you were asking. 我希望这就是你所要求的。

 var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); function start() { context.clearRect(0, 0, canvas.width, canvas.height); drawCurves(context, step); step += 5; window.requestAnimationFrame(start); } var step = -4; function drawCurves(ctx, step) { var width = ctx.canvas.width; var height = ctx.canvas.height; ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = "rgb(66,44,255)"; var x = 0; var y = 0; var amplitude = 10; var frequency = height / (2 * Math.PI); ctx.save(); ctx.translate(-amplitude * Math.sin(step / frequency), 0); while (y < height) { x = width / 2 + amplitude * Math.sin((y + step) / frequency); ctx.lineTo(x, y); y++; } //ctx.closePath(); ctx.stroke(); ctx.restore(); } start(); 
 canvas { background-color: wheat; } div { width: 100px; height: 400px; border: solid; } 
 <div class="box"> <canvas id="canvas" width="100" height="400"></canvas> </div> 

UPDATE UPDATE

In the case you need to use several curves you can do it like this: 如果您需要使用多条曲线,您可以这样做:

I'm putting all the functionality for drawing the wave in a function drawWave that takes the amplitude and the trigonometric function to be used (sin or cos) as arguments: 我将所有功能用于在函数drawWave中绘制波形,该函数使用振幅和三角函数(sin或cos)作为参数:

 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var width = ctx.canvas.width; var height = ctx.canvas.height; var step = -4; function start() { window.requestAnimationFrame(start); ctx.clearRect(0, 0, canvas.width, canvas.height); drawWave(10,"sin"); drawWave(10,"cos"); drawWave(5,"sin"); step += 5; } function drawWave(amplitude,trig){ // trig is the trigonometric function to be used: sin or cos ctx.beginPath(); ctx.lineWidth = 2; ctx.strokeStyle = "rgb(66,44,255)"; var x = 0; var y = 0; //var amplitude = 10; var frequency = height / (2 * Math.PI); ctx.save(); ctx.translate(-amplitude * Math[trig](step / frequency), 0); while (y < height) { x = width / 2 + amplitude * Math[trig]((y + step) / frequency); ctx.lineTo(x, y); y++; } ctx.stroke(); ctx.restore(); } start(); 
 canvas { background-color: wheat; } div { width: 100px; height: 400px; border: solid; } 
 <div class="box"> <canvas id="canvas" width="100" height="400"></canvas> </div> 

GLSL version GLSL版本

Because uv-coordinates in this fragment shader varies from 0 to 1 it is very simple to reach the goal, you only need wave frequency divisable by pi. 因为此片段着色器中的uv坐标从0到1变化,所以达到目标非常简单,只需要pi可以分频的波频率。

 let gl = canvas.getContext('webgl'); gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, 3, -1, -1, 3, -1]), gl.STATIC_DRAW); let pid = gl.createProgram(); shader(`attribute vec2 v;void main(void){gl_Position=vec4(v.xy,0.,1.);}`,gl.VERTEX_SHADER); shader(document.querySelector(`script[type="glsl"]`).textContent,gl.FRAGMENT_SHADER); gl.linkProgram(pid); gl.useProgram(pid); let v = gl.getAttribLocation(pid, "v"); gl.vertexAttribPointer(v, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(v); let resolution = gl.getUniformLocation(pid, 'resolution'); let time = gl.getUniformLocation(pid, 'time'); requestAnimationFrame(draw); function draw(t) { gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.clearColor(0, 0, 0, 0); gl.uniform1f(time, t/500); gl.uniform2f(resolution, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.drawArrays(gl.TRIANGLES, 0, 3); requestAnimationFrame(draw); } function shader(src, type) { let sid = gl.createShader(type); gl.shaderSource(sid, src); gl.compileShader(sid); gl.attachShader(pid, sid); } 
 <canvas width="200" height="600" id="canvas"/> <script type="glsl"> precision highp float; uniform float time; uniform vec2 resolution; void main(void) { vec2 uv = gl_FragCoord.xy / resolution.xy; vec2 p = 20.*uv - 10.; vec3 f = vec3(0.); f+=pow(abs(p.x+5.*sin(time*2.)*sin(uv.y*6.28*2.)+cos(uv.y*11.)),-0.8)*vec3(.5,.0,.5); f+=pow(abs(p.x+4.*sin(time*3.)*sin(uv.y*6.28*.5)+cos(uv.y*21.)),-0.8)*vec3(.5,.5,.0); f+=pow(abs(p.x+3.*sin(time*5.)*sin(uv.y*6.28*1.)+cos(uv.y*17.)),-0.8)*vec3(.0,.5,.5); gl_FragColor = vec4(f, 1.); } </script> 

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

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