Skip to content

Instantly share code, notes, and snippets.

@kylebradshaw
Forked from gkhays/DrawSineWave.html
Created July 8, 2020 02:12
Show Gist options
  • Select an option

  • Save kylebradshaw/8336476cc6584bfacb80f98f4ebbfe25 to your computer and use it in GitHub Desktop.

Select an option

Save kylebradshaw/8336476cc6584bfacb80f98f4ebbfe25 to your computer and use it in GitHub Desktop.
Oscillating sine wave, including the steps to figuring out how to plot a sine wave

Draw a Sine Wave in JavaScript

To Do

  • Add links to JSFiddle

I am revisiting the Fourier transform so I thought it might be nice to come up with some visualizations. My first stop was to plot a sine wave in JavaScript, then to animate it. I am using the window.requestAnimationFrame() method. I've documented the steps in reverse order.

Simple Animation

I'm fairly happy with the animation.

Animated Sine Wave

The JavaScript funtion to plot the sine wave uses the Math.sin() function, which is called repeatedly given a different starting point on the y-axis. See the simple plot below. In this case, the draw() function makes the repeat calls via window.requestAnimationFrame(draw).

function draw() {
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");

    context.clearRect(0, 0, 500, 500);
    showAxes(context);
    context.save();            
    
    plotSine(context, step, 50);
    context.restore();
    
    step += 4;
    window.requestAnimationFrame(draw);
}

Superimposed Sine Waves

After I learned to plot a sine wave, I visualized how to draw multiple sine waves in order to achieve the oscillation effect in the animation. It looked pretty cool, so I get it around. It reminds me of Spirograph. 😄

Superimposed

The step advances the starting point along the y-axis.

var step = 4;
for (var i = -4; i < canvas.height; i += step) {
    plotSine(context, i, 54 + i);
}

Simple Plot

My initial attempt to draw a sine wave on an HTML5 canvas.

Sine Wave

function plotSine(ctx) {
    var width = ctx.canvas.width;
    var height = ctx.canvas.height;
    var scale = 20;

    ctx.beginPath();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "rgb(66,44,255)";
    
    var x = 0;
    var y = 0;
    var amplitude = 40;
    var frequency = 20;
    //ctx.moveTo(x, y);
    while (x < width) {
        y = height/2 + amplitude * Math.sin(x/frequency);
        ctx.lineTo(x, y);
        x = x + 1;
    }
    ctx.stroke();
}

Interesting tidbit: If we uncomment ctx.moveTo(x, y) just before the loop we get a vertical line.

References

<!DOCTYPE html>
<html>
<head>
<title>Sine Wave</title>
<script type="text/javascript">
function showAxes(ctx,axes) {
var width = ctx.canvas.width;
var height = ctx.canvas.height;
var xMin = 0;
ctx.beginPath();
ctx.strokeStyle = "rgb(128,128,128)";
// X-Axis
ctx.moveTo(xMin, height/2);
ctx.lineTo(width, height/2);
// Y-Axis
ctx.moveTo(width/2, 0);
ctx.lineTo(width/2, height);
// Starting line
ctx.moveTo(0, 0);
ctx.lineTo(0, height);
ctx.stroke();
}
function drawPoint(ctx, y) {
var radius = 3;
ctx.beginPath();
// Hold x constant at 4 so the point only moves up and down.
ctx.arc(4, y, radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();
ctx.lineWidth = 1;
ctx.stroke();
}
function plotSine(ctx, xOffset, yOffset) {
var width = ctx.canvas.width;
var height = ctx.canvas.height;
var scale = 20;
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "rgb(66,44,255)";
// console.log("Drawing point...");
// drawPoint(ctx, yOffset+step);
var x = 4;
var y = 0;
var amplitude = 40;
var frequency = 20;
//ctx.moveTo(x, y);
ctx.moveTo(x, 50);
while (x < width) {
y = height/2 + amplitude * Math.sin((x+xOffset)/frequency);
ctx.lineTo(x, y);
x++;
// console.log("x="+x+" y="+y);
}
ctx.stroke();
ctx.save();
console.log("Drawing point at y=" + y);
drawPoint(ctx, y);
ctx.stroke();
ctx.restore();
}
function draw() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.clearRect(0, 0, 500, 500);
showAxes(context);
context.save();
plotSine(context, step, 50);
context.restore();
step += 4;
window.requestAnimationFrame(draw);
}
function spirograph() {
var canvas2 = document.getElementById("canvas2");
var context = canvas2.getContext("2d");
showAxes(context);
context.save();
// var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var step = 4;
for (var i = -4; i < canvas.height; i += step) {
// context.putImageData(imageData, 0, 0);
plotSine(context, i, 54 + i);
}
}
function init() {
window.requestAnimationFrame(draw);
spirograph();
}
var step = -4;
</script>
</head>
<body onload="init()">
<h3>Oscillating Sine Wave</h3>
<canvas id="canvas" width="500" height="100"></canvas>
<p/>
<h3>Multiple Sine Waves</h3>
<canvas id="canvas2" width="500" height="100"/>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment