The code below generates a sine wave with a specified amplitude, frequency, and phase. The wave is drawn on the Canvas using the lineTo
method, which creates a line from the current position to the specified x
and y
coordinates. The wave is redrawn on each frame of the animation using the requestAnimationFrame
method, with the phase value incremented slightly to create the appearance of movement.
<canvas id="waveCanvas" width="600" height="400" style="width: 600px; height: 400px;"></canvas>
var canvas = document.getElementById("waveCanvas");
var ctx = canvas.getContext("2d");
var amplitude = 100;
var frequency = 0.05;
var phase = 0;
function drawWave() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(0, canvas.height / 2);
for(var x = 0; x < canvas.width; x++) {
var y = amplitude * Math.sin(frequency * x + phase);
ctx.lineTo(x, y + canvas.height / 2);
}
ctx.strokeStyle = "blue";
ctx.stroke();
phase += 0.05;
requestAnimationFrame(drawWave);
}
drawWave();
Next, I added an amplitude function. The amplitude value is incremented by a random value within a specified range, causing the wave to wiggle. I can now adjust the wiggleAmplitude
value to control the strength of the wiggle effect.
var canvas = document.getElementById("waveCanvas");
var ctx = canvas.getContext("2d");
var amplitude = 100;
var frequency = 0.05;
var phase = 0;
var wiggleAmplitude = 5;
function drawWave() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(0, canvas.height / 2);
amplitude += Math.random() * wiggleAmplitude - wiggleAmplitude / 2;
for(var x = 0; x < canvas.width; x++) {
var y = amplitude * Math.sin(frequency * x + phase);
ctx.lineTo(x, y + canvas.height / 2);
}
ctx.strokeStyle = "blue";
ctx.stroke();
phase += 0.05;
requestAnimationFrame(drawWave);
}
drawWave();
Optionally, I can set the strokeStyle
of the Canvas context to a random hexadecimal color value, so that the wave will be drawn in a different color on each frame of the animation. This creates a dynamic and colorful effect for the wave. I can adjust the range of the random color values to create different color palettes for the wave. I have not used the code below in my final code, as the result was too flickering.
ctx.strokeStyle = "#" + Math.floor(Math.random() * 16777215).toString(16);
ctx.stroke();
After messing with the variables and adding a bit more randomness, I got a nice, futuristic since wave.
var canvas = document.getElementById("waveCanvas");
var ctx = canvas.getContext("2d");
var amplitude = 10;
var frequency = 0.05;
var phase = 0;
var wiggleAmplitude = 5;
function drawWave() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(0, canvas.height / 2);
amplitude += Math.random() * wiggleAmplitude - wiggleAmplitude / 2;
var gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, "#57076B");
gradient.addColorStop(0.25, "#D058EE");
gradient.addColorStop(0.5, "#C110EB");
gradient.addColorStop(0.75, "#5E286B");
gradient.addColorStop(1, "#950DB8");
ctx.strokeStyle = gradient;
for (var x = 0; x < canvas.width; x++) {
var y = amplitude * Math.sin(frequency * x + phase);
y += Math.random() * 10 - 5; // add random noise to y value
var lineWidth = Math.random() * 10 + 1; // generate random line width between 1 and 11
ctx.lineWidth = lineWidth;
ctx.lineTo(x, y + canvas.height / 2);
}
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.shadowColor = "#F6055D";
ctx.shadowBlur = Math.random() * 72 + 1;
ctx.shadowOffsetY = 8;
ctx.stroke();
phase += 0.05;
requestAnimationFrame(drawWave);
}
drawWave();
See a demo below:
See the Pen JavaScript Canvas Sine Wave by Ciprian (@ciprian) on CodePen.