JSFiddle - React, Tailwind, and code Playground
HTML
<header class="center">
<button class="center">
<span class="buttonText">🦟モスキート音を鳴らす</span>
</button>
</header>
CSS
* {
box-sizing: border-box;
}
html,
body {
font-family: helvetica;
height: 100%;
margin: 0;
}
.center {
display: flex;
justify-content: center;
align-items: center;
}
header {
width: 100%;
height: 100%;
background: #fff;
flex-direction: column;
border: 20px solid #eee;
}
h1 {
margin: 0px auto 25px;
font-size: 65px;
font-weight: 700;
letter-spacing: 0.5px;
line-height: 50px;
}
h2 {
max-width: 450px;
font-size: 15px;
font-weight: normal;
text-align: center;
margin: 0 10px 20px;
line-height: 22px;
}
button {
padding: 10px 15px;
border: 2px solid;
border-radius: 3px;
background: #fefefe;
cursor: pointer;
transition: background-color 200ms;
max-width: 80vw;
}
button:hover {
background: #eee;
}
button span {
font-size: 24px;
display: inline-block;
}
.flip {
transform: scale(-1, 1);
}
.buttonText {
font-size: 14px;
letter-spacing: 0.6px;
padding: 0 10px;
font-weight: bold;
}
i {
opacity: 0.7;
}
.about {
padding-top: 20px;
font-size: 14px;
text-align: center;
padding-left: 30px;
padding-right: 30px;
}
@media only screen and (max-width: 600px) {
h1 {
font-size: 40px;
}
}
JavaScript
// Create Audio Context (Safari still uses the prefix here)
const context = new (window.AudioContext || window.webkitAudioContext)();
// Oscillator at 700hz frequency (I hear mosquitos are more, but this sounds right to my old ears)
const oscillator = context.createOscillator();
oscillator.type = "sawtooth";
oscillator.frequency.setValueAtTime(700, context.currentTime);
// A Gain node allows me to change the volume of our annoying 700hz sawtooth mosquito
const gainNode = context.createGain();
gainNode.connect(context.destination);
// I put another gain node to reduce the noise a ton because its insanely annoying
// This can probably be merged into the previous one, but reads easier here to me.
const lowVolumeFixedGain = context.createGain();
lowVolumeFixedGain.gain.value = 0.003;
lowVolumeFixedGain.connect(gainNode);
// Connect them all together.
oscillator.connect(lowVolumeFixedGain);
// So far, this makes for a boring mosquito. Now to add some variance.
// Gonna use some radians
const increase = Math.PI * 2 / 100
let sineWaveCounter = 0;
let sineWaveEffect = 0;
const gainOffset = 0.8;
// Randomly push and pull by small amounts. Used to both detune and to change the volume
const randomVariancePush = 0.02;
let randomVariance = 0;
// The real magic. There are probably better values, I tweaked these for 5 minutes
// and 5 hours later, I still feel like I have a tab open with this code in it.
const annoyingSinBasedDetuneMultiplier = 7
const annoyingRandomBasedDetuneMultiplier = 14
const annoyingSinBasedGainMultipier = 0.3
const annoyingRandomBasedGainMultiplier = 0.6
// Potato gonna Potate, Mosquito gonna mosquite
function mosquite() {
// The sine wave, alternating between -1 & 1
sineWaveEffect = Math.sin(sineWaveCounter) / 2;
// Detune the osccilator in the sin wave pattern, and also with the random variance!
oscillator.detune.value = sineWaveEffect * annoyingSinBasedDetuneMultiplier + randomVariance * annoyingRandomBasedDetuneMultiplier;
...