Загрузка данных
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Почасовая мелодия</title>
<style>
body {
font-family: Arial, sans-serif;
background: #f2f2f2;
text-align: center;
padding-top: 80px;
}
button {
font-size: 18px;
padding: 14px 24px;
margin: 10px;
border: none;
border-radius: 8px;
cursor: pointer;
color: white;
}
#start {
background: #2196f3;
}
#test {
background: #4caf50;
}
#status {
margin-top: 25px;
font-size: 18px;
}
</style>
</head>
<body>
<h1>🔔 Почасовая мелодия</h1>
<button id="start"> ▶ Включить расписание </button>
<button id="test"> 🔊 Тест — сыграть сейчас </button>
<div id="status"> Расписание не запущено </div>
<script>
let audioContext = null;
let timer = null;
// ========================================
// Создаём AudioContext после нажатия
// ========================================
function initAudio() {
if(!audioContext) {
audioContext = new(window.AudioContext || window.webkitAudioContext)();
}
if(audioContext.state === "suspended") {
audioContext.resume();
}
}
// ========================================
// Проигрывание мелодии
// ========================================
function playMelody() {
initAudio();
const ctx = audioContext;
let time = ctx.currentTime;
// Частота + длительность
const melody = [
[523.25, 0.25], // До
[659.25, 0.25], // Ми
[783.99, 0.25], // Соль
[1046.50, 0.50], // До
[783.99, 0.25], // Соль
[659.25, 0.25], // Ми
[523.25, 0.50] // До
];
for(const [frequency, duration] of melody) {
const oscillator = ctx.createOscillator();
const gain = ctx.createGain();
oscillator.type = "sine";
oscillator.frequency.value = frequency;
// Плавное включение
gain.gain.setValueAtTime(0, time);
gain.gain.linearRampToValueAtTime(0.3, time + 0.02);
// Плавное выключение
gain.gain.linearRampToValueAtTime(0, time + duration - 0.02);
oscillator.connect(gain);
gain.connect(ctx.destination);
oscillator.start(time);
oscillator.stop(time + duration);
time += duration;
}
}
// ========================================
// Кнопка "Тест"
// ========================================
document.getElementById("test").addEventListener("click", () => {
playMelody();
document.getElementById("status").innerHTML = "🔊 Тестовая мелодия играет";
});
// ========================================
// Кнопка "Запустить расписание"
// ========================================
document.getElementById("start").addEventListener("click", () => {
initAudio();
// Если расписание уже запущено,
// второй таймер не создаём
if(timer !== null) {
return;
}
timer = setInterval(checkTime, 1000);
document.getElementById("status").innerHTML = "✅ Расписание запущено. Мелодия прозвучит за 10 и 2 минуты до каждого часа.";
// Проверяем время сразу
checkTime();
});
// ========================================
// Проверяем время
// ========================================
function checkTime() {
const now = new Date();
/*
Например:
15:50 → играем
15:58 → играем
16:50 → играем
16:58 → играем
...
*/
if((now.getMinutes() === 50 || now.getMinutes() === 58) && now.getSeconds() < 2) {
playMelody();
document.getElementById("status").innerHTML = "🔔 Мелодия! Следующая — через час.";
}
}
</script>
</body>
</html>