JSFiddle - React, Tailwind, and code Playground
by fxi
HTML
<canvas id='c'></canvas>
CSS
html,
body {
height: 100%;
width: 100%;
overflow:hidden;
}
body {
display: flex;
align-items: center;
justify-content: centeR;
flex-direction:column;
}
#c {
width:100%;
height:100%;
position:absolute;
z-index:-1;
top:0;
left:0;
}
JavaScript
const Actx = window.AudioContext || window.webkitAudioContext;
const audioCtx = new Actx();
const analyser = audioCtx.createAnalyser();
analyser.fftSize = 2048;
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
analyser.getByteTimeDomainData(dataArray);
class Os {
constructor(opt) {
this._opt = Object.assign({}, {
type: 'sine',
min: 0,
max: 100,
step : 10,
color: '#000'
}, opt);
this._enabled = false;
this._init = false;
this.update = this.update.bind(this);
/**
* audio
*/
this.audioCtx = this.o.audioCtx;
const oscillator = this.audioCtx.createOscillator();
oscillator.type = this.o.type;
oscillator.connect(analyser);
analyser.connect(this.audioCtx.destination);
this.oscillator = oscillator;
/**
* ui
*/
const elInput = document.createElement('input');
elInput.setAttribute('type', 'range');
elInput.setAttribute('min', this.o.min - 1);
elInput.setAttribute('max', this.o.max);
elInput.setAttribute('value', this.o.min - 1);
elInput.setAttribute('step', this.o.step);
elInput.addEventListener('input', this.update);
elInput.style.accentColor = this.o.color;
document.body.appendChild(elInput);
}
get o() {
return this._opt;
}
update(e) {
const hz = (e.target.value * 1);
if (hz >= this.o.min) {
this.start();
} else {
this.stop();
return;
}
this.hz(hz);
}
hz(v) {
this.oscillator.frequency.setValueAtTime(v, this.audioCtx.currentTime);
}
start() {
if (this.enabled) {
return;
}
if (!this._init) {
this.oscillator.start();
this._init = true;
}
this.enabled = true;
}
stop() {
if (!this.enabled) {
return;
}
this.hz(0);
this.enabled = false;
}
}
for (let i = 1; i < 3; i++) {
new Os({
audioCtx:...