<div id="controls">
<div>
<p>Frequency: <span id="cycles">1</span>Hz</p>
<p class="holder">
<span>1Hz</span>
<input type="range" id="hertz" min="1" max="100" step="0.5" value="1">
<span>100Hz</span>
</p>
</div>
<div>
<p>Amplitude: <span id="amplitudeLabel">1</span></p>
<p class="holder">
<span>0</span>
<input type="range" id="amplitude" min="0" max="1" step="0.001" value="1">
<span>1</span>
</p>
</div>
<div>
<p>Phase Shift: <span id="shiftLabel">0</span>π</p>
<p class="holder">
<span>0</span>
<input type="range" id="shift" min="0" max="3.15" step="0.01" value="0">
<span>2π</span>
</p>
</div>
</div>
<canvas id="chart" height="600" width="1440"></canvas>
body
{
font-family:"Microsoft Sans Serif","sans";
color: lightgrey;
background-color:#1d3030;
}
#controls
{
margin:1em;
diplay:flex;
}
#controls div
{
display: inline-block;
flex: 1 1 30%;
margin-right:0.5em;
}
p
{
background-color:#305050;
width:300px;
border-radius: 0.3em;
padding:0.5em;
margin:0;
margin-bottom:3px;
}
.holder
{
text-align: center;
}
.holder span
{
vertical-align:top;
}
const chartElement = document.getElementById('chart');
const w = chartElement.width;
const h = chartElement.height;
const midW = w/2;
const midH = h/2;
const chartContext = chartElement.getContext('2d');
const hertzSlider = document.getElementById('hertz');
const cyclesLabel = document.getElementById('cycles');
let frequency = 1;
hertzSlider.addEventListener('input', e =>
{
cyclesLabel.innerHTML = e.target.value;
frequency = e.target.value;
plotSine();
});
const amplitudeSlider = document.getElementById('amplitude');
const amplitudeLabel = document.getElementById('amplitudeLabel');
let amplitude = 1;
amplitudeSlider.addEventListener('input', e =>
{
amplitudeLabel.innerHTML = e.target.value;
amplitude = e.target.value;
plotSine();
});
const shiftSlider = document.getElementById('shift');
const shiftLabel = document.getElementById('shiftLabel');
let shift = 0;
shiftSlider.setAttribute('max', Math.PI*2);
shiftSlider.setAttribute('step', Math.PI/100);
shiftSlider.addEventListener('input', e =>
{
shiftLabel.innerHTML = (e.target.value / Math.PI).toFixed(2);
shift = parseFloat(e.target.value);
plotSine();
});
function getY(x, zeroOffsetX, zeroOffsetY)
{
let degrees = ((x-zeroOffsetX)/w) * 720;
let rads = (degrees/360)*Math.PI*2;
let value = (rads)*frequency;
let y = (Math.sin(value+shift)*midH*amplitude) + zeroOffsetY;
return y;
}
function plotSine()
{
chartContext.strokeStyle = 'limegreen';
chartContext.fillStyle = 'black';
chartContext.fillRect(0,0,w,h);
chartContext.lineWidth = 1;
chartContext.beginPath();
chartContext.moveTo(midW, 0);
chartContext.lineTo(midW, h);
chartContext.moveTo(0, midH);
chartContext.lineTo(w, midH);
chartContext.stroke();
chartContext.fillStyle = 'limegreen';
chartContext.font = '1em monospace';
chartContext.fillText('0 seconds', 0, midH+15);
chartContext.fillText('1', midW, midH+15);
chartContext.fillText('2', w-10, midH+15);
chartContext.fillText('1', midW-15, 15);
chartContext.fillText('0', midW-15, midH);
chartContext.fillText('-1', midW-25, h);
const zeroOffsetX = midW;
const zeroOffsetY = midH;
const T = 1/frequency;
chartContext.lineWidth = 2;
chartContext.beginPath();
chartContext.moveTo(0, getY(0, zeroOffsetX, zeroOffsetY));
for(let x = 0; x < w; x += T)
{
let y = getY(x, zeroOffsetX, zeroOffsetY);
chartContext.lineTo(x, y);
}
chartContext.stroke();
}
plotSine();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.