/* ============================================
ケニア式高重心ランニング音声システム
TCD FORCE テーマ用 カスタムスクリプト
※ 外観 > TCDテーマオプション > カスタムスクリプト に貼り付け
============================================ */
document.addEventListener('DOMContentLoaded', function() {
'use strict';
// 要素が存在しない場合は処理しない
if (!document.querySelector('.getta-audio-system')) return;
// プログラムデータ
var phases = [
{
id: 1,
name: "ウォームアップ",
duration: 180,
description: "リラックスして走り出しましょう",
instructions: [
{ time: 0, text: "プログラムを開始します。まずはリラックスして、普段のペースで走り始めてください。" },
{ time: 15, text: "深呼吸をしながら、体の力を抜いていきます。" },
{ time: 30, text: "肩の力を抜いて、腕を自然に振りましょう。" },
{ time: 50, text: "呼吸を整えます。鼻から吸って、口から吐く。" },
{ time: 70, text: "今の自分の重心の位置を感じてみてください。どこにありますか?" },
{ time: 90, text: "多くの人は、腰より下に重心があります。" },
{ time: 110, text: "これから、ケニア人ランナーのように重心を高くしていきます。" },
{ time: 130, text: "焦らず、ゆっくりと変化を感じていきましょう。" },
{ time: 150, text: "ウォームアップ完了まであと30秒です。" },
{ time: 170, text: "次のフェーズに移ります。" }
]
},
{
id: 2,
name: "姿勢リセット",
duration: 180,
description: "背骨をまっすぐ、頭を高く",
instructions: [
{ time: 0, text: "姿勢リセットを始めます。まず、頭のてっぺんを意識してください。" },
{ time: 15, text: "頭のてっぺんから、空に向かって糸で引っ張られているイメージです。" },
{ time: 30, text: "背骨がすーっと伸びていきます。" },
{ time: 45, text: "あごを軽く引いて、視線は15メートル先を見ましょう。" },
{ time: 60, text: "肩が上がっていませんか?力を抜いて、肩を下げます。" },
{ time: 80, text: "背中が丸まらないように。胸を少し開きます。" },
{ time: 100, text: "頭が前に出すぎていませんか?耳と肩が一直線になるように。" },
{ time: 120, text: "この姿勢をキープしながら走ります。" },
{ time: 140, text: "頭頂部から引き上げられている感覚を忘れずに。" },
{ time: 160, text: "良い姿勢が保てています。次は骨盤に意識を向けます。" }
]
},
{
id: 3,
name: "骨盤前傾",
duration: 240,
description: "骨盤を前に傾け、重心を上げる",
instructions: [
{ time: 0, text: "骨盤前傾のフェーズです。ここがケニア式走法の核心です。" },
{ time: 15, text: "両手を腰に当ててみてください。骨盤の位置を確認します。" },
{ time: 30, text: "おへそを、少し前に突き出すイメージです。" },
{ time: 50, text: "お尻を後ろに引くのではなく、骨盤全体を前に傾けます。" },
{ time: 70, text: "腰が反りすぎないように注意。自然な前傾です。" },
{ time: 90, text: "骨盤が前傾すると、自然と重心が前に移動します。" },
{ time: 110, text: "前に倒れそうになる感覚があれば、それが正解です。" },
{ time: 130, text: "その倒れそうな力を、前への推進力に変えます。" },
{ time: 150, text: "脚を前に出すというより、体が前に進む感覚です。" },
{ time: 170, text: "おへそを前に。骨盤を前に。この意識を保ちます。" },
{ time: 190, text: "ケニア人ランナーは、この骨盤前傾が自然にできています。" },
{ time: 210, text: "あなたの体も、少しずつこの姿勢を覚えていきます。" },
{ time: 230, text: "骨盤前傾のフェーズ、完了です。" }
]
},
{
id: 4,
name: "高重心イメージング",
duration: 300,
description: "みぞおちに重心を置く",
instructions: [
{ time: 0, text: "高重心イメージングを始めます。最も重要なフェーズです。" },
{ time: 20, text: "みぞおちの位置を意識してください。おへその少し上です。" },
{ time: 40, text: "そこに、ボールが入っているとイメージしてください。" },
{ time: 60, text: "そのボールが、あなたの重心です。" },
{ time: 80, text: "普段、このボールは腰の下にあります。" },
{ time: 100, text: "今、そのボールをみぞおちまで持ち上げます。" },
{ time: 120, text: "重心が上がると、体が軽くなる感覚があります。" },
{ time: 140, text: "脚が下にぶら下がっているだけ、というイメージです。" },
{ time: 160, text: "みぞおちから脚が生えている。そう感じてください。" },
{ time: 180, text: "上半身で走る。脚はついてくるだけ。" },
{ time: 200, text: "ケニア人ランナーの重心は、みぞおちにあります。" },
{ time: 220, text: "だから、彼らの走りは軽やかに見えるのです。" },
{ time: 240, text: "みぞおちに重心。この感覚を体に刻みます。" },
{ time: 260, text: "脚の力みが抜けていませんか?それが正解です。" },
{ time: 280, text: "高重心の感覚、つかめてきましたか?" }
]
},
{
id: 5,
name: "着地の修正",
duration: 240,
description: "フォアフット着地へ移行",
instructions: [
{ time: 0, text: "着地の修正フェーズです。高重心が保てていれば、着地も変わります。" },
{ time: 20, text: "今、足のどこで着地していますか?" },
{ time: 40, text: "かかとから着地していると、ブレーキになります。" },
{ time: 60, text: "高重心のまま、足の真ん中から前で着地してみましょう。" },
{ time: 80, text: "足裏全体で、地面をとらえる感覚です。" },
{ time: 100, text: "着地は体の真下で。前に足を投げ出さないように。" },
{ time: 120, text: "ドスドスではなく、タタタという軽い着地音を目指します。" },
{ time: 140, text: "地面からの反発を感じてください。" },
{ time: 160, text: "その反発を、次の一歩の推進力に使います。" },
{ time: 180, text: "アキレス腱がバネのように働く感覚です。" },
{ time: 200, text: "足首は固めすぎず、柔らかく使います。" },
{ time: 220, text: "着地の修正フェーズ、完了です。" }
]
},
{
id: 6,
name: "統合・定着",
duration: 300,
description: "すべてを統合し、体に覚えさせる",
instructions: [
{ time: 0, text: "最終フェーズ。統合と定着です。" },
{ time: 20, text: "これまでの要素をすべて統合していきます。" },
{ time: 40, text: "頭頂部から引き上げられる姿勢。" },
{ time: 60, text: "骨盤は前傾。おへそを前に。" },
{ time: 80, text: "重心はみぞおち。高い位置に。" },
{ time: 100, text: "着地は体の真下で、フォアフット。" },
{ time: 120, text: "すべてが連動して、効率的な走りになります。" },
{ time: 140, text: "今のこの感覚を、体に覚えさせてください。" },
{ time: 160, text: "これがケニア人ランナーの走り方です。" },
{ time: 180, text: "このプログラムを繰り返し聴くことで、体が覚えていきます。" },
{ time: 200, text: "週に2回から3回、続けてみてください。" },
{ time: 220, text: "1ヶ月後には、無意識でこの走りができるようになります。" },
{ time: 240, text: "あなたの走りは、確実に変わっていきます。" },
{ time: 260, text: "最後まで、この感覚を維持しましょう。" },
{ time: 280, text: "プログラム終了まで、あと少しです。" }
]
}
];
// 状態管理
var currentPhase = 0;
var currentInstructionIndex = 0;
var isPlaying = false;
var isPaused = false;
var elapsedTime = 0;
var phaseElapsedTime = 0;
var timerInterval = null;
var speechSynthesis = window.speechSynthesis;
var repeatMode = false;
// DOM要素
var elements = {
progressPhase: document.getElementById('gasProgressPhase'),
progressPercent: document.getElementById('gasProgressPercent'),
progressFill: document.getElementById('gasProgressFill'),
phaseNumber: document.getElementById('gasPhaseNumber'),
phaseTitle: document.getElementById('gasPhaseTitle'),
phaseDesc: document.getElementById('gasPhaseDesc'),
timerDisplay: document.getElementById('gasTimerDisplay'),
wave: document.getElementById('gasWave'),
instruction: document.getElementById('gasInstruction'),
btnPlay: document.getElementById('gasBtnPlay'),
btnPrev: document.getElementById('gasBtnPrev'),
btnNext: document.getElementById('gasBtnNext'),
btnReset: document.getElementById('gasBtnReset'),
btnRepeat: document.getElementById('gasBtnRepeat'),
btnRestart: document.getElementById('gasBtnRestart'),
playIcon: document.getElementById('gasPlayIcon'),
phasesList: document.getElementById('gasPhasesList'),
complete: document.getElementById('gasComplete'),
speed: document.getElementById('gasSpeed'),
speedValue: document.getElementById('gasSpeedValue'),
pitch: document.getElementById('gasPitch'),
pitchValue: document.getElementById('gasPitchValue'),
interval: document.getElementById('gasInterval')
};
// 初期化
function init() {
renderPhasesList();
setupEventListeners();
updateUI();
}
// フェーズリスト描画
function renderPhasesList() {
var html = '';
for (var i = 0; i < phases.length; i++) {
var phase = phases[i];
var minutes = Math.floor(phase.duration / 60);
var seconds = phase.duration % 60;
var timeStr = seconds > 0 ? minutes + '分' + seconds + '秒' : minutes + '分';
html += '
' +
'
' + phase.id + '
' +
'
' +
'
' + phase.name + '
' +
'
' + timeStr + '
' +
'
';
}
elements.phasesList.innerHTML = html;
// フェーズクリックイベント
var phaseItems = document.querySelectorAll('.gas-phase-item');
for (var j = 0; j < phaseItems.length; j++) {
phaseItems[j].addEventListener('click', function() {
var phaseIndex = parseInt(this.getAttribute('data-phase'));
goToPhase(phaseIndex);
});
}
}
// イベントリスナー設定
function setupEventListeners() {
elements.btnPlay.addEventListener('click', togglePlay);
elements.btnPrev.addEventListener('click', prevPhase);
elements.btnNext.addEventListener('click', nextPhase);
elements.btnReset.addEventListener('click', resetProgram);
elements.btnRepeat.addEventListener('click', toggleRepeat);
elements.btnRestart.addEventListener('click', restartProgram);
elements.speed.addEventListener('input', function() {
elements.speedValue.textContent = this.value + 'x';
});
elements.pitch.addEventListener('input', function() {
elements.pitchValue.textContent = this.value;
});
}
// 再生/一時停止切り替え
function togglePlay() {
if (!isPlaying) {
startProgram();
} else if (isPaused) {
resumeProgram();
} else {
pauseProgram();
}
}
// プログラム開始
function startProgram() {
isPlaying = true;
isPaused = false;
elements.complete.classList.remove('show');
updatePlayButton();
setWaveAnimation(true);
startTimer();
speakCurrentInstruction();
updateUI();
elements.btnPrev.disabled = false;
elements.btnNext.disabled = false;
}
// プログラム一時停止
function pauseProgram() {
isPaused = true;
updatePlayButton();
setWaveAnimation(false);
stopTimer();
speechSynthesis.cancel();
}
// プログラム再開
function resumeProgram() {
isPaused = false;
updatePlayButton();
setWaveAnimation(true);
startTimer();
}
// プログラムリセット
function resetProgram() {
speechSynthesis.cancel();
stopTimer();
currentPhase = 0;
currentInstructionIndex = 0;
elapsedTime = 0;
phaseElapsedTime = 0;
isPlaying = false;
isPaused = false;
elements.complete.classList.remove('show');
updatePlayButton();
setWaveAnimation(false);
updateUI();
elements.btnPrev.disabled = true;
elements.btnNext.disabled = true;
elements.instruction.querySelector('.gas-instruction-text').textContent = '準備ができたら再生ボタンを押してください';
}
// プログラム再スタート
function restartProgram() {
resetProgram();
startProgram();
}
// リピートモード切り替え
function toggleRepeat() {
repeatMode = !repeatMode;
elements.btnRepeat.style.background = repeatMode ? '#0891b2' : '';
elements.btnRepeat.style.color = repeatMode ? '#ffffff' : '';
}
// 前のフェーズ
function prevPhase() {
if (currentPhase > 0) {
goToPhase(currentPhase - 1);
}
}
// 次のフェーズ
function nextPhase() {
if (currentPhase < phases.length - 1) {
goToPhase(currentPhase + 1);
} else if (repeatMode) {
goToPhase(0);
} else {
completeProgram();
}
}
// 指定フェーズへ移動
function goToPhase(phaseIndex) {
speechSynthesis.cancel();
currentPhase = phaseIndex;
currentInstructionIndex = 0;
phaseElapsedTime = 0;
elapsedTime = 0;
for (var i = 0; i < phaseIndex; i++) {
elapsedTime += phases[i].duration;
}
updateUI();
if (isPlaying && !isPaused) {
speakCurrentInstruction();
}
}
// プログラム完了
function completeProgram() {
speechSynthesis.cancel();
stopTimer();
isPlaying = false;
isPaused = false;
updatePlayButton();
setWaveAnimation(false);
speak("プログラムが完了しました。お疲れ様でした。高重心の感覚を忘れずに、これからも練習を続けてください。");
elements.complete.classList.add('show');
}
// タイマー開始
function startTimer() {
stopTimer();
timerInterval = setInterval(function() {
elapsedTime++;
phaseElapsedTime++;
updateTimerDisplay();
updateProgress();
checkInstructions();
checkPhaseEnd();
}, 1000);
}
// タイマー停止
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
}
// タイマー表示更新
function updateTimerDisplay() {
var minutes = Math.floor(elapsedTime / 60);
var seconds = elapsedTime % 60;
elements.timerDisplay.textContent =
(minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
// プログレス更新
function updateProgress() {
var totalDuration = 0;
for (var i = 0; i < phases.length; i++) {
totalDuration += phases[i].duration;
}
var percent = Math.round((elapsedTime / totalDuration) * 100);
elements.progressFill.style.width = percent + '%';
elements.progressPercent.textContent = percent + '%';
}
// 指示チェック
function checkInstructions() {
var phase = phases[currentPhase];
var instructions = phase.instructions;
for (var i = currentInstructionIndex; i < instructions.length; i++) {
if (phaseElapsedTime >= instructions[i].time && i === currentInstructionIndex) {
speakInstruction(instructions[i].text);
currentInstructionIndex = i + 1;
break;
}
}
}
// フェーズ終了チェック
function checkPhaseEnd() {
var phase = phases[currentPhase];
if (phaseElapsedTime >= phase.duration) {
nextPhase();
}
}
// 現在の指示を読み上げ
function speakCurrentInstruction() {
var phase = phases[currentPhase];
if (phase.instructions.length > 0) {
speakInstruction(phase.instructions[0].text);
currentInstructionIndex = 1;
}
}
// 指示を読み上げ
function speakInstruction(text) {
elements.instruction.querySelector('.gas-instruction-text').textContent = text;
speak(text);
}
// 音声合成
function speak(text) {
speechSynthesis.cancel();
var utterance = new SpeechSynthesisUtterance(text);
utterance.lang = 'ja-JP';
utterance.rate = parseFloat(elements.speed.value);
utterance.pitch = parseFloat(elements.pitch.value);
utterance.volume = 1;
var voices = speechSynthesis.getVoices();
for (var i = 0; i < voices.length; i++) {
if (voices[i].lang.indexOf('ja') !== -1) {
utterance.voice = voices[i];
break;
}
}
speechSynthesis.speak(utterance);
}
// 再生ボタン更新
function updatePlayButton() {
if (!isPlaying || isPaused) {
elements.playIcon.innerHTML = '';
} else {
elements.playIcon.innerHTML = '';
}
}
// 波形アニメーション設定
function setWaveAnimation(active) {
var bars = elements.wave.querySelectorAll('.gas-wave-bar');
for (var i = 0; i < bars.length; i++) {
if (active) {
bars[i].classList.add('active');
bars[i].classList.remove('paused');
} else {
bars[i].classList.remove('active');
bars[i].classList.add('paused');
}
}
}
// UI更新
function updateUI() {
var phase = phases[currentPhase];
elements.phaseNumber.textContent = phase.id;
elements.phaseTitle.textContent = phase.name;
elements.phaseDesc.textContent = phase.description;
elements.progressPhase.textContent = phase.id + ' / ' + phases.length + ': ' + phase.name;
var phaseItems = document.querySelectorAll('.gas-phase-item');
for (var i = 0; i < phaseItems.length; i++) {
phaseItems[i].classList.remove('active', 'completed');
if (i === currentPhase) {
phaseItems[i].classList.add('active');
} else if (i < currentPhase) {
phaseItems[i].classList.add('completed');
}
}
updateTimerDisplay();
updateProgress();
}
// 音声リスト読み込み
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = function() {};
}
// 初期化実行
init();
});
–
開始準備
再生ボタンを押してプログラムを開始してください
設定
インターバル
⚠️ 安全のために 外音が聞こえるイヤホンを使用し、交通安全に十分注意してください。
プログラム完了!
お疲れ様でした。高重心の感覚を体に覚えさせましょう。
Copyright © 2010