Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Анимированная синусоида с фиксированными начальной и конечной точками

#javascript #css3 #html5 #svg #css_animation


У меня есть синусоидальная волна на холсте, которая качается влево и вправо. Я пытаюсь
добиться того, чтобы начальная и конечная точки оставались зафиксированными. Как это
сделать?



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








  







    


Ответы

Ответ 1



GLSL вариация на тему, добиться желаемого эффекта просто за счет того что система координат в этом шейдере от 0 до 1, соответственно частота должна быть кратна пи 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'); gl.uniform2f(resolution, gl.drawingBufferWidth, gl.drawingBufferHeight); 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.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); } codepen: https://codepen.io/strangerintheq/pen/xNBayG

Ответ 2



Я изменил размер вашего холста, потому что хотел увидеть его весь. Вы можете изменить его размер обратно на то, что вам нужно. Я сделал 2 вещи: Частота должна быть переменной frequency = height / (2 * Math.PI); или frequency = height / (4 * Math.PI) ;. Делитель должен быть кратным - 2 * Math.PI Я перенаправляю контекст в противоположном направлении с теми же значениями: ctx.translate (-amplitude * Math.sin (step / frequency), 0); Если вам нужно более тонкое регулирование колебания, играйте с амплитудой. В моем коде есть закомментированная ctx.closePath(). Пожалуйста, раскомментируйте эту строку, чтобы ясно увидеть, что синусоида остается фиксированной в центре. Я надеюсь, что это то, что вы спрашивали. 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; }
UPDATE В том случае, если вам нужно использовать несколько кривых, вы можете сделать это так: Я помещаю все функции для рисования волны в функцию drawWwing, которая принимает в качестве аргументов амплитуду и тригонометрическую функцию (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; }


Комментариев нет:

Отправить комментарий