182 lines
6.3 KiB
JavaScript
182 lines
6.3 KiB
JavaScript
var EXERCISES = [
|
|
{ ico: "🌬️", name: "Тыныс алу жаттығуы", dur: 60, desc: "Диафрагмамен терең тыныста: ішті үрлеп жұт, баяу шығар" },
|
|
{ ico: "🙆", name: "Мойын қозғалыстары", dur: 60, desc: "Мойынды баяу алға-артқа, солға-оңға еңкейт (айналдырмай)" },
|
|
{ ico: "🤸", name: "Иық айналдыру", dur: 60, desc: "Иықты алға, содан артқа айналдыр — әр бағытта 10 рет" },
|
|
{ ico: "✊", name: "Қол буындарын қозғау", dur: 45, desc: "Жұдырық жұм, аш; саусақтарды веермен жаз" },
|
|
{ ico: "🐱", name: "«Мысық пен сиыр»", dur: 60, desc: "Төрт аяқтап тұрып, арқаны дөңгелектеп, содан иілдір" },
|
|
{ ico: "🦵", name: "Жамбас буындары", dur: 60, desc: "Шалқадан жатып, тізені кеудеге тарт, екінші аяқты түзу ұста" },
|
|
{ ico: "🦿", name: "Тізе қозғалыстары", dur: 60, desc: "Отырып немесе жатып, тізені баяу бүк-жаз" },
|
|
{ ico: "🦶", name: "Тобық айналдыру", dur: 45, desc: "Әр аяқтың тобығын сағат тілімен және қарсы айналдыр" }
|
|
];
|
|
|
|
var state = {
|
|
list: document.getElementById("exList"),
|
|
ring: document.getElementById("ring"),
|
|
time: document.getElementById("time"),
|
|
name: document.getElementById("timerName"),
|
|
startBtn: document.getElementById("startBtn"),
|
|
resetBtn: document.getElementById("resetBtn"),
|
|
skipBtn: document.getElementById("skipBtn"),
|
|
autoBtn: document.getElementById("autoBtn"),
|
|
progText: document.getElementById("progText"),
|
|
progBar: document.getElementById("progBar"),
|
|
index: 0,
|
|
running: false,
|
|
auto: false,
|
|
left: EXERCISES[0].dur,
|
|
total: 0,
|
|
int: null
|
|
};
|
|
|
|
function fmt(s) {
|
|
var m = Math.floor(s / 60), ss = s % 60;
|
|
return (m < 10 ? "0" : "") + m + ":" + (ss < 10 ? "0" : "") + ss;
|
|
}
|
|
|
|
function render() {
|
|
var html = EXERCISES.map(function (e, i) {
|
|
var cls = i === state.index ? " active" : "";
|
|
if (state.auto && i === state.index) cls = " on";
|
|
if (state.auto && i < state.index) cls = " done";
|
|
var st = i < state.index ? "✓" : (i === state.index && state.running ? "…" : fmt(e.dur));
|
|
return '<div class="ex' + cls + '" data-i="' + i + '">' +
|
|
'<div class="ex-ico">' + e.ico + '</div>' +
|
|
'<div class="ex-body"><div class="ex-name">' + e.name + '</div>' +
|
|
'<div class="ex-time">' + e.desc + '</div></div>' +
|
|
'<div class="ex-state">' + st + '</div></div>';
|
|
}).join("");
|
|
state.list.innerHTML = html;
|
|
state.list.querySelectorAll(".ex").forEach(function (el) {
|
|
el.addEventListener("click", function () { pick(parseInt(el.dataset.i, 10)); });
|
|
});
|
|
updateRing();
|
|
updateProg();
|
|
}
|
|
|
|
function updateRing() {
|
|
var done = state.total - state.left;
|
|
var pct = state.total > 0 ? (done / state.total) * 360 : 0;
|
|
state.ring.style.background = "conic-gradient(var(--cyan) " + pct + "deg, #223043 0deg)";
|
|
state.time.textContent = fmt(state.left);
|
|
state.name.textContent = EXERCISES[state.index].name;
|
|
}
|
|
|
|
function updateProg() {
|
|
if (!state.auto) {
|
|
state.progText.textContent = "Жеке жаттығу";
|
|
state.progBar.style.width = "0%";
|
|
return;
|
|
}
|
|
var done = state.index;
|
|
state.progText.textContent = (done + 1) + " / " + EXERCISES.length;
|
|
state.progBar.style.width = (done / EXERCISES.length * 100) + "%";
|
|
}
|
|
|
|
function beep() {
|
|
try {
|
|
var ctx = new (window.AudioContext || window.webkitAudioContext)();
|
|
var o = ctx.createOscillator(), g = ctx.createGain();
|
|
o.connect(g); g.connect(ctx.destination);
|
|
o.frequency.value = 660; g.gain.value = 0.18;
|
|
o.start();
|
|
setTimeout(function () { o.stop(); ctx.close(); }, 350);
|
|
} catch (e) {}
|
|
}
|
|
|
|
function stop() {
|
|
clearInterval(state.int);
|
|
state.int = null;
|
|
state.running = false;
|
|
state.startBtn.textContent = "▶ Бастау";
|
|
}
|
|
|
|
function tick() {
|
|
state.left--;
|
|
if (state.left <= 0) {
|
|
beep();
|
|
next();
|
|
return;
|
|
}
|
|
updateRing();
|
|
}
|
|
|
|
function start() {
|
|
if (state.running) { stop(); render(); return; }
|
|
state.running = true;
|
|
state.startBtn.textContent = "⏸ Тоқтау";
|
|
state.int = setInterval(tick, 1000);
|
|
render();
|
|
}
|
|
|
|
function next() {
|
|
clearInterval(state.int);
|
|
state.int = null;
|
|
if (state.auto) {
|
|
state.index++;
|
|
if (state.index >= EXERCISES.length) {
|
|
state.auto = false;
|
|
state.index = 0;
|
|
state.left = EXERCISES[0].dur;
|
|
state.total = EXERCISES[0].dur;
|
|
state.running = false;
|
|
state.autoBtn.textContent = "🎯 Толық кешенді бастау (барлық 8 жаттығу)";
|
|
state.startBtn.textContent = "▶ Бастау";
|
|
beep(); beep();
|
|
render();
|
|
return;
|
|
}
|
|
state.left = EXERCISES[state.index].dur;
|
|
state.total = state.left;
|
|
render();
|
|
state.running = true;
|
|
state.int = setInterval(tick, 1000);
|
|
return;
|
|
}
|
|
state.index = (state.index + 1) % EXERCISES.length;
|
|
state.left = EXERCISES[state.index].dur;
|
|
state.total = state.left;
|
|
state.running = false;
|
|
render();
|
|
}
|
|
|
|
function pick(i) {
|
|
stop();
|
|
state.auto = false;
|
|
state.autoBtn.textContent = "🎯 Толық кешенді бастау (барлық 8 жаттығу)";
|
|
state.index = i;
|
|
state.left = EXERCISES[i].dur;
|
|
state.total = state.left;
|
|
render();
|
|
}
|
|
|
|
function reset() {
|
|
stop();
|
|
state.left = EXERCISES[state.index].dur;
|
|
state.total = state.left;
|
|
render();
|
|
}
|
|
|
|
function startAuto() {
|
|
stop();
|
|
state.auto = true;
|
|
state.index = 0;
|
|
state.left = EXERCISES[0].dur;
|
|
state.total = state.left;
|
|
state.autoBtn.textContent = "⏸ Кешен жүріп жатыр…";
|
|
state.startBtn.textContent = "▶ Бастау";
|
|
render();
|
|
start();
|
|
}
|
|
|
|
state.startBtn.addEventListener("click", start);
|
|
state.resetBtn.addEventListener("click", reset);
|
|
state.skipBtn.addEventListener("click", function () { stop(); next(); });
|
|
state.autoBtn.addEventListener("click", startAuto);
|
|
|
|
render();
|
|
|
|
var io = new IntersectionObserver(function (entries) {
|
|
entries.forEach(function (e) { if (e.isIntersecting) e.target.classList.add("in"); });
|
|
}, { threshold: .15 });
|
|
document.querySelectorAll(".reveal").forEach(function (el) { io.observe(el); });
|