javascript - Animating sine wave in js - Stack Overflow

I'm trying to animate a sine wave in JS but it's not acting as expected. I'm using a <

I'm trying to animate a sine wave in JS but it's not acting as expected. I'm using a <canvas> element along with window.requestAnimationFrame() method but it's a CPU hog and as i change frequency with the slider it just break and show random waveforms. I also don't know if drawing adjacent lines is the best way to represent a sine wave. Please note that i'll use vanilla JS and that the sine's frequency and amplitude are variables set by sliders. Thanks in advance.

This is what i got so far:

UPDATE: i worked on it and this is the new version:

var canvas = document.querySelector("canvas"),
  ctx = canvas.getContext("2d"),
  cHeight = canvas.height,
  cWidth = canvas.width,
  frequency = document.querySelector("#f").value,
  amplitude = 80,
  x = 0,
  y = cHeight / 2,
  point_y = 0;

window.onload = init;

function init() {
  document.querySelector("#f").addEventListener("input", function() {
    frequency = this.value;
    document.querySelector("#output_f").value = frequency;
  }, false);

  drawSine();
}

function drawSine() {
  ctx.clearRect(0, 0, cWidth, cHeight);

  ctx.beginPath();
  ctx.moveTo(0, y);
  ctx.strokeStyle = "red";
  ctx.lineTo(cWidth, y);
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.strokeStyle = "black";
  for (x = 0; x < 600; x++) {
    point_y = amplitude * -Math.sin((frequency / 95.33) * x) + y;
    ctx.lineTo(x, point_y);
  }
  ctx.stroke();
  ctx.closePath();
  requestAnimationFrame(drawSine);
}
canvas {
  border: 1px solid red;
  margin: 10px;
}
<input id="f" type="range" min="0" max="20000" value="20" step="1">
<output for="f" id="output_f">20</output>
<canvas width="600px" height="200px"></canvas>

I'm trying to animate a sine wave in JS but it's not acting as expected. I'm using a <canvas> element along with window.requestAnimationFrame() method but it's a CPU hog and as i change frequency with the slider it just break and show random waveforms. I also don't know if drawing adjacent lines is the best way to represent a sine wave. Please note that i'll use vanilla JS and that the sine's frequency and amplitude are variables set by sliders. Thanks in advance.

This is what i got so far: http://cssdeck./labs/8cq5vclp

UPDATE: i worked on it and this is the new version: http://cssdeck./labs/sbfynjkr

var canvas = document.querySelector("canvas"),
  ctx = canvas.getContext("2d"),
  cHeight = canvas.height,
  cWidth = canvas.width,
  frequency = document.querySelector("#f").value,
  amplitude = 80,
  x = 0,
  y = cHeight / 2,
  point_y = 0;

window.onload = init;

function init() {
  document.querySelector("#f").addEventListener("input", function() {
    frequency = this.value;
    document.querySelector("#output_f").value = frequency;
  }, false);

  drawSine();
}

function drawSine() {
  ctx.clearRect(0, 0, cWidth, cHeight);

  ctx.beginPath();
  ctx.moveTo(0, y);
  ctx.strokeStyle = "red";
  ctx.lineTo(cWidth, y);
  ctx.stroke();
  ctx.closePath();

  ctx.beginPath();
  ctx.strokeStyle = "black";
  for (x = 0; x < 600; x++) {
    point_y = amplitude * -Math.sin((frequency / 95.33) * x) + y;
    ctx.lineTo(x, point_y);
  }
  ctx.stroke();
  ctx.closePath();
  requestAnimationFrame(drawSine);
}
canvas {
  border: 1px solid red;
  margin: 10px;
}
<input id="f" type="range" min="0" max="20000" value="20" step="1">
<output for="f" id="output_f">20</output>
<canvas width="600px" height="200px"></canvas>

Share Improve this question edited Jun 3, 2019 at 9:19 Roko C. Buljan 207k41 gold badges328 silver badges340 bronze badges asked May 29, 2014 at 8:31 plumbe0plumbe0 1071 gold badge1 silver badge9 bronze badges 5
  • It looks blocky and broken because you are doing i*10 as your x co-ordinate. Remove the *10 and reduce the frequency by a few thousand fold and it is much smoother. – Elle Commented May 29, 2014 at 9:02
  • @JordanTrudgett i tried removing the *10 but it's still broken. The frequency range needs to be from 20 to 20k Hz as the sine represents a sound. I noticed that it draws the same, wrong, sines periodically: try 440 and 6710 (or 8000 and 17000) and you will get the ~same result. – plumbe0 Commented May 29, 2014 at 11:15
  • What's happening is that because x is an integer value (i.e. a pixel) you will get patterns determined by the error from the real curve, try using (x*0.01) and see the values again, you can notice in this smaller sample of the curve the small errors that make the wave look 'bouncy' - if that is what you mean by broken. Or you could explain more what you expect. Perhaps look at Nyquist Frequency for a better explanation of discrete sampling. – Elle Commented May 30, 2014 at 12:53
  • @JordanTrudgett i searched a bit and i found that my problem is related to aliasing. Any way i can handle it? Also i discovered AnalyserNode and i think that could really solve the problem, but i didn't understand it fully. – plumbe0 Commented May 30, 2014 at 15:44
  • For an inspiration, this can be a good start (though it's not originally in JavaScript). – Mahozad Commented Nov 22, 2024 at 6:40
Add a ment  | 

2 Answers 2

Reset to default 3

I've messed around with sine waves quite a bit, because I'm working on a little project that involves animated sine waves. I've got some code you might be interested in taking a look at. Like mentioned earlier, you need to make sure you are using the right increment in your loop so the lines do not look jagged.

https://jsfiddle/uawLvymc/

window.requestAnimationFrame = window.requestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.msRequestAnimationFrame ||
function(f) {
  return setTimeout(f, 1000 / 60)
};

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var startTime = new Date().getTime();

function getPath(height) {
  var width = canvas.width;
  var spacing = 0.08;
  var loopNum = 0;
  var pointList = [];
  var i = 0;

  for (i = 0; i < width / 2; i++) {
    pointList[loopNum] = [loopNum, Math.sin(loopNum * spacing) * (i * height) + 100];
    loopNum++;
  }
  for (i = width / 2; i > 0; i--) {
     pointList[loopNum] = [loopNum, Math.sin(loopNum * spacing) * (i * height) + 100];
     loopNum++;
  }
  return pointList;
}

function draw() {
  var currentTime = new Date().getTime();
  var runTime = currentTime - startTime;

  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath();
  ctx.lineWidth = 2;
  ctx.strokeStyle = "rgb(80, 100, 230)";

  var height = Math.sin(runTime * 0.008) * 0.2;
  var pointList = getPath(height);

  for (var i = 0; i < 500; i++) {
    if (i === 0) {
      ctx.moveTo(pointList[0][0], pointList[0][1]);
    } else {
      ctx.lineTo(pointList[i][0], pointList[i][1]);
    }
  }
  ctx.stroke();

  window.requestAnimationFrame(draw);
}

window.requestAnimationFrame(draw);

Sorry I didn't really edit down the code, it's just a direct copy from what I was working on. Hope it helps though.

See if this example could help you a little

Sine Wave Example canvas

    function init()
    {
        setInterval(OnDraw, 200);
    }

    var time = 0;
    var color = "#ff0000";

    function OnDraw()
    {
        time = time + 0.2;
        var canvas = document.getElementById("mycanvas");
        var dataLine = canvas.getContext("2d");
        var value = document.getElementById("lineWidth");

        dataLine.clearRect(0, 0, canvas.width, canvas.height);

        dataLine.beginPath();

        for(cnt = -1; cnt <= canvas.width; cnt++)
        {
            dataLine.lineTo(cnt, canvas.height * 0.5 - (Math.random() * 2 + Math.cos(time + cnt * 0.05) * 20 ));
        }

        dataLine.lineWidth = value.value * 0.1;
        dataLine.strokeStyle = color;
        dataLine.stroke();
    }

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744096902a4558108.html

相关推荐

  • javascript - Animating sine wave in js - Stack Overflow

    I'm trying to animate a sine wave in JS but it's not acting as expected. I'm using a <

    8天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信