纯 JS 合成音效,无需外部音频文件。6种音色覆盖常见交互场景。
首次需要用户点击激活 AudioContext。
let _actx;
function getAudioCtx() {
if (!_actx) _actx = new (AudioContext || webkitAudioContext)();
return _actx;
}
function sfxBubble() {
const a = getAudioCtx(), o = a.createOscillator(), g = a.createGain();
o.type='sine'; o.frequency.setValueAtTime(600,a.currentTime);
o.frequency.exponentialRampToValueAtTime(200,a.currentTime+0.18);
g.gain.setValueAtTime(0.12,a.currentTime);
g.gain.exponentialRampToValueAtTime(0.001,a.currentTime+0.2);
o.connect(g).connect(a.destination); o.start(); o.stop(a.currentTime+0.2);
}
function sfxClick() {
const a = getAudioCtx(), o = a.createOscillator(), g = a.createGain();
o.type='square'; o.frequency.value=800;
g.gain.setValueAtTime(0.1,a.currentTime);
g.gain.exponentialRampToValueAtTime(0.001,a.currentTime+0.06);
o.connect(g).connect(a.destination); o.start(); o.stop(a.currentTime+0.06);
}
function sfxEntry() {
const a = getAudioCtx();
[440,550,660].forEach((f,i) => {
const o = a.createOscillator(), g = a.createGain();
o.type='sine'; o.frequency.value=f;
g.gain.setValueAtTime(0.08, a.currentTime+i*0.08);
g.gain.exponentialRampToValueAtTime(0.001, a.currentTime+i*0.08+0.15);
o.connect(g).connect(a.destination);
o.start(a.currentTime+i*0.08); o.stop(a.currentTime+i*0.08+0.15);
});
}
function sfxStomp() {
const a = getAudioCtx(), o = a.createOscillator(), g = a.createGain();
o.type='triangle'; o.frequency.value=110;
g.gain.setValueAtTime(0.18,a.currentTime);
g.gain.exponentialRampToValueAtTime(0.001,a.currentTime+0.12);
o.connect(g).connect(a.destination); o.start(); o.stop(a.currentTime+0.12);
}
function sfxGrow() {
const a = getAudioCtx(), o = a.createOscillator(), g = a.createGain();
o.type='sine'; o.frequency.value=880;
g.gain.setValueAtTime(0.1,a.currentTime);
g.gain.exponentialRampToValueAtTime(0.001,a.currentTime+0.3);
o.connect(g).connect(a.destination); o.start(); o.stop(a.currentTime+0.3);
}
function sfxTrans() {
const a = getAudioCtx(), o = a.createOscillator(), g = a.createGain();
o.type='triangle'; o.frequency.setValueAtTime(330,a.currentTime);
o.frequency.exponentialRampToValueAtTime(660,a.currentTime+0.25);
g.gain.setValueAtTime(0.08,a.currentTime);
g.gain.exponentialRampToValueAtTime(0.001,a.currentTime+0.3);
o.connect(g).connect(a.destination); o.start(); o.stop(a.currentTime+0.3);
}