交互体验 节奏器edit icon

Fork(复制)
下载
嵌入
BUG反馈
index.html
现在支持上传本地图片了!
index.html
            
            <!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>千金散尽 - 节奏打击器</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#8C1515',
                        secondary: '#D4AF37',
                        tertiary: '#E8C39E',
                        background: '#F9F5F0',
                        textDark: '#333333',
                    },
                    fontFamily: {
                        sans: ['Noto Sans SC', 'sans-serif'],
                        serif: ['Noto Serif SC', 'serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-shadow {
                text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
            }
            .animate-pulse {
                animation: pulse 0.5s ease-in-out;
            }
            .animate-beat {
                animation: beat 0.3s ease-in-out;
            }
            .keyboard-key {
                transition: all 0.1s ease;
            }
            .keyboard-key.active {
                transform: translateY(4px);
                background-color: #D4AF37;
                box-shadow: 0 2px 4px rgba(0,0,0,0.2);
            }
        }

        @keyframes pulse {
            0%, 100% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.05);
            }
        }

        @keyframes beat {
            0%, 100% {
                transform: scale(1);
            }
            50% {
                transform: scale(1.2);
            }
        }

        /* 滑块样式 */
        input[type="range"] {
            -webkit-appearance: none;
            height: 8px;
            border-radius: 5px;
            background: #e0e0e0;
            outline: none;
        }

        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background: #8C1515;
            cursor: pointer;
            transition: background .3s;
        }

        input[type="range"]::-webkit-slider-thumb:hover {
            background: #D4AF37;
        }

        /* 开关样式 */
        .toggle-switch {
            position: relative;
            display: inline-block;
            width: 60px;
            height: 30px;
        }

        .toggle-switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }

        .slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            transition: .4s;
            border-radius: 34px;
        }

        .slider:before {
            position: absolute;
            content: "";
            height: 22px;
            width: 22px;
            left: 4px;
            bottom: 4px;
            background-color: white;
            transition: .4s;
            border-radius: 50%;
        }

        input:checked + .slider {
            background-color: #8C1515;
        }

        input:focus + .slider {
            box-shadow: 0 0 1px #8C1515;
        }

        input:checked + .slider:before {
            transform: translateX(30px);
        }
    </style>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&family=Noto+Serif+SC:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body class="bg-background text-textDark min-h-screen flex flex-col">
    <!-- 页面头部 -->
    <header class="bg-primary text-white py-10 overflow-hidden relative">
        <div class="absolute inset-0 bg-[url('https://picsum.photos/seed/poetry/1920/400')] bg-cover bg-center opacity-20"></div>
        <div class="absolute inset-0 bg-gradient-to-r from-primary/80 to-primary/60"></div>
        <div class="container mx-auto px-4 relative z-10">
            <h1 class="text-[clamp(2rem,4vw,3rem)] font-serif text-center text-shadow">千金散尽 - 节奏打击器</h1>
            <p class="text-[clamp(1rem,1.5vw,1.2rem)] text-center mt-3 max-w-2xl mx-auto opacity-90">
                模拟诗句断句与重音,感受李白诗歌的韵律之美
            </p>
        </div>
    </header>

    <main class="flex-grow container mx-auto px-4 py-12">
        <!-- 诗句显示区 -->
        <section class="mb-12 text-center">
            <div class="bg-white rounded-lg shadow-xl p-6 md:p-8 max-w-3xl mx-auto border-l-4 border-primary">
                <h2 class="text-2xl font-serif font-bold mb-6 text-primary">诗韵节奏</h2>
                <div class="relative">
                    <div id="poem-display" class="text-2xl md:text-3xl font-serif leading-relaxed mb-6">
                        <span id="char-1" class="inline-block px-2 py-1 mx-1">千</span>
                        <span id="char-2" class="inline-block px-2 py-1 mx-1">金</span>
                        <span id="char-3" class="inline-block px-2 py-1 mx-1">散</span>
                        <span id="char-4" class="inline-block px-2 py-1 mx-1">尽</span>
                        <span id="char-5" class="inline-block px-2 py-1 mx-1">还</span>
                        <span id="char-6" class="inline-block px-2 py-1 mx-1">复</span>
                        <span id="char-7" class="inline-block px-2 py-1 mx-1">来</span>
                    </div>
                    <div class="absolute -bottom-4 left-1/2 transform -translate-x-1/2 w-16 h-1 bg-secondary rounded-full"></div>
                </div>
                <p class="text-lg text-gray-600 italic">
                    《将进酒》 - 李白
                </p>
            </div>
        </section>

        <!-- 控制面板 -->
        <section class="mb-12">
            <div class="bg-white rounded-lg shadow-xl p-6 md:p-8 max-w-4xl mx-auto">
                <h2 class="text-2xl font-serif font-bold mb-6 text-primary">控制面板</h2>
                
                <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                    <!-- 左侧:速度和音量控制 -->
                    <div>
                        <div class="mb-6">
                            <label class="block text-lg font-medium mb-2">节奏速度 (BPM)</label>
                            <div class="flex items-center">
                                <i class="fa fa-tachometer text-primary mr-3"></i>
                                <input type="range" id="tempo-control" min="40" max="200" value="80" class="w-full">
                                <span id="tempo-value" class="ml-3 min-w-[3rem] text-center">80</span>
                            </div>
                        </div>
                        
                        <div class="mb-6">
                            <label class="block text-lg font-medium mb-2">音量</label>
                            <div class="flex items-center">
                                <i class="fa fa-volume-up text-primary mr-3"></i>
                                <input type="range" id="volume-control" min="0" max="100" value="70" class="w-full">
                                <span id="volume-value" class="ml-3 min-w-[3rem] text-center">70</span>
                            </div>
                        </div>
                        
                        <div class="mb-6">
                            <label class="block text-lg font-medium mb-2">自动播放</label>
                            <div class="flex items-center">
                                <i class="fa fa-play-circle text-primary mr-3"></i>
                                <label class="toggle-switch">
                                    <input type="checkbox" id="auto-play">
                                    <span class="slider"></span>
                                </label>
                                <span class="ml-3">开启自动循环</span>
                            </div>
                        </div>
                        
                        <!-- 新增:乐器选择 -->
                        <div class="mb-6">
                            <label class="block text-lg font-medium mb-2">乐器选择</label>
                            <div class="flex items-center">
                                <i class="fa fa-music text-primary mr-3"></i>
                                <select id="instrument-select" class="w-full border border-gray-300 rounded-md p-2 focus:outline-none focus:ring-2 focus:ring-primary">
                                    <option value="piano">钢琴</option>
                                    <option value="drum">鼓</option>
                                    <option value="guzheng">古筝</option>
                                    <option value="chimes">编钟</option>
                                </select>
                            </div>
                        </div>
                    </div>
                    
                    <!-- 右侧:重音设置 -->
                    <div>
                        <label class="block text-lg font-medium mb-2">重音设置</label>
                        <p class="text-sm text-gray-600 mb-4">点击字符设置重音强度:弱(灰色) → 中(红色) → 强(金色)</p>
                        
                        <div id="stress-controls" class="grid grid-cols-7 gap-2 mb-6">
                            <div class="stress-control text-center" data-char="1">
                                <div class="keyboard-key h-12 rounded-md bg-gray-200 flex items-center justify-center cursor-pointer mb-1">千</div>
                                <span class="text-xs">弱</span>
                            </div>
                            <div class="stress-control text-center" data-char="2">
                                <div class="keyboard-key h-12 rounded-md bg-primary/60 flex items-center justify-center cursor-pointer mb-1">金</div>
                                <span class="text-xs">中</span>
                            </div>
                            <div class="stress-control text-center" data-char="3">
                                <div class="keyboard-key h-12 rounded-md bg-gray-200 flex items-center justify-center cursor-pointer mb-1">散</div>
                                <span class="text-xs">弱</span>
                            </div>
                            <div class="stress-control text-center" data-char="4">
                                <div class="keyboard-key h-12 rounded-md bg-secondary flex items-center justify-center cursor-pointer mb-1">尽</div>
                                <span class="text-xs">强</span>
                            </div>
                            <div class="stress-control text-center" data-char="5">
                                <div class="keyboard-key h-12 rounded-md bg-gray-200 flex items-center justify-center cursor-pointer mb-1">还</div>
                                <span class="text-xs">弱</span>
                            </div>
                            <div class="stress-control text-center" data-char="6">
                                <div class="keyboard-key h-12 rounded-md bg-primary/60 flex items-center justify-center cursor-pointer mb-1">复</div>
                                <span class="text-xs">中</span>
                            </div>
                            <div class="stress-control text-center" data-char="7">
                                <div class="keyboard-key h-12 rounded-md bg-secondary flex items-center justify-center cursor-pointer mb-1">来</div>
                                <span class="text-xs">强</span>
                            </div>
                        </div>
                        
                        <div class="flex justify-center space-x-4 mt-6">
                            <button id="play-btn" class="bg-primary hover:bg-primary/90 text-white px-6 py-3 rounded-md transition-colors duration-200 flex items-center">
                                <i class="fa fa-play mr-2"></i> 播放
                            </button>
                            <button id="reset-btn" class="bg-gray-300 hover:bg-gray-400 text-gray-800 px-6 py-3 rounded-md transition-colors duration-200 flex items-center">
                                <i class="fa fa-refresh mr-2"></i> 重置
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- 节奏键盘 -->
        <section class="mb-12">
            <div class="bg-white rounded-lg shadow-xl p-6 md:p-8 max-w-6xl mx-auto">
                <h2 class="text-2xl font-serif font-bold mb-6 text-primary">节奏键盘</h2>
                <p class="text-center text-gray-600 mb-6">
                    点击或使用键盘按键 (A-S-D-F-G-H-J) 模拟诗句断句节奏
                </p>
                
                <div id="keyboard" class="grid grid-cols-7 gap-2">
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-gray-200 flex flex-col items-center justify-center cursor-pointer border-2 border-gray-300 hover:border-primary" data-key="1">
                        <span class="text-xl md:text-2xl font-serif">千</span>
                        <span class="text-xs mt-1">A</span>
                    </div>
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-primary/60 flex flex-col items-center justify-center cursor-pointer border-2 border-primary/80 hover:border-primary" data-key="2">
                        <span class="text-xl md:text-2xl font-serif">金</span>
                        <span class="text-xs mt-1">S</span>
                    </div>
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-gray-200 flex flex-col items-center justify-center cursor-pointer border-2 border-gray-300 hover:border-primary" data-key="3">
                        <span class="text-xl md:text-2xl font-serif">散</span>
                        <span class="text-xs mt-1">D</span>
                    </div>
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-secondary flex flex-col items-center justify-center cursor-pointer border-2 border-secondary/80 hover:border-primary" data-key="4">
                        <span class="text-xl md:text-2xl font-serif">尽</span>
                        <span class="text-xs mt-1">F</span>
                    </div>
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-gray-200 flex flex-col items-center justify-center cursor-pointer border-2 border-gray-300 hover:border-primary" data-key="5">
                        <span class="text-xl md:text-2xl font-serif">还</span>
                        <span class="text-xs mt-1">G</span>
                    </div>
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-primary/60 flex flex-col items-center justify-center cursor-pointer border-2 border-primary/80 hover:border-primary" data-key="6">
                        <span class="text-xl md:text-2xl font-serif">复</span>
                        <span class="text-xs mt-1">H</span>
                    </div>
                    <div class="keyboard-key h-20 md:h-32 rounded-lg bg-secondary flex flex-col items-center justify-center cursor-pointer border-2 border-secondary/80 hover:border-primary" data-key="7">
                        <span class="text-xl md:text-2xl font-serif">来</span>
                        <span class="text-xs mt-1">J</span>
                    </div>
                </div>
            </div>
        </section>

        <!-- 节奏模式 -->
        <section class="mb-12">
            <div class="bg-white rounded-lg shadow-xl p-6 md:p-8 max-w-4xl mx-auto">
                <h2 class="text-2xl font-serif font-bold mb-6 text-primary">预设节奏模式</h2>
                <p class="text-center text-gray-600 mb-6">
                    选择一种预设节奏模式开始,也可以根据需要调整参数
                </p>
                
                <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div class="p-4 border-2 border-primary/30 rounded-lg hover:border-primary transition-colors duration-200 cursor-pointer bg-primary/5 rhythm-pattern" data-pattern="1">
                        <h3 class="font-bold text-lg mb-2">古典吟诵</h3>
                        <p class="text-sm text-gray-600">
                            模拟传统诗词吟诵节奏,重音在"金"、"尽"、"来"
                        </p>
                    </div>
                    <div class="p-4 border-2 border-gray-200 rounded-lg hover:border-primary transition-colors duration-200 cursor-pointer rhythm-pattern" data-pattern="2">
                        <h3 class="font-bold text-lg mb-2">豪放洒脱</h3>
                        <p class="text-sm text-gray-600">
                            节奏明快,重音在"千"、"散"、"还",体现李白豪放风格
                        </p>
                    </div>
                    <div class="p-4 border-2 border-gray-200 rounded-lg hover:border-primary transition-colors duration-200 cursor-pointer rhythm-pattern" data-pattern="3">
                        <h3 class="font-bold text-lg mb-2">沉吟思索</h3>
                        <p class="text-sm text-gray-600">
                            节奏缓慢,重音均匀分布,表现沉思的状态
                        </p>
                    </div>
                    <div class="p-4 border-2 border-gray-200 rounded-lg hover:border-primary transition-colors duration-200 cursor-pointer rhythm-pattern" data-pattern="4">
                        <h3 class="font-bold text-lg mb-2">跌宕起伏</h3>
                        <p class="text-sm text-gray-600">
                            节奏变化大,重音在"千"、"尽"、"复",表现情感的起伏
                        </p>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <footer class="bg-primary text-white py-8">
        <div class="container mx-auto px-4">
            <div class="text-center">
                <h2 class="text-xl font-serif mb-4">千金散尽 - 节奏打击器</h2>
                <p class="max-w-2xl mx-auto mb-6 text-sm opacity-80">
                    探索李白诗歌的韵律之美,通过调整节奏和重音感受不同的诗歌表达
                </p>
                <div class="flex justify-center space-x-4">
                    <a href="#" class="text-white hover:text-secondary transition-colors duration-200">
                        <i class="fa fa-book"></i> 诗歌库
                    </a>
                    <a href="#" class="text-white hover:text-secondary transition-colors duration-200">
                        <i class="fa fa-info-circle"></i> 使用指南
                    </a>
                    <a href="#" class="text-white hover:text-secondary transition-colors duration-200">
                        <i class="fa fa-cog"></i> 设置
                    </a>
                </div>
                <p class="mt-6 text-xs opacity-70">
                    © 2023 千金散尽 - 节奏打击器 | 基于李白诗歌韵律设计
                </p>
            </div>
        </div>
    </footer>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // 节奏数据
            const rhythmData = {
                stress: [0, 1, 0, 2, 0, 1, 2], // 0:弱, 1:中, 2:强
                tempo: 80, // BPM
                volume: 70,
                autoPlay: false,
                currentPattern: 1,
                instrument: 'piano' // 新增:当前乐器
            };
            
            // 预设节奏模式
            const rhythmPatterns = [
                { name: "古典吟诵", stress: [0, 1, 0, 2, 0, 1, 2] },
                { name: "豪放洒脱", stress: [2, 0, 2, 0, 2, 0, 1] },
                { name: "沉吟思索", stress: [1, 0, 1, 0, 1, 0, 1] },
                { name: "跌宕起伏", stress: [2, 0, 1, 2, 0, 2, 0] }
            ];
            
            // 音频资源(示例URL,实际项目中应替换为真实音频文件)
            const audioAssets = {
                piano: {
                    low: 'https://example.com/audio/piano_low.mp3',
                    medium: 'https://example.com/audio/piano_medium.mp3',
                    high: 'https://example.com/audio/piano_high.mp3'
                },
                drum: {
                    low: 'https://example.com/audio/drum_low.mp3',
                    medium: 'https://example.com/audio/drum_medium.mp3',
                    high: 'https://example.com/audio/drum_high.mp3'
                },
                guzheng: {
                    low: 'https://example.com/audio/guzheng_low.mp3',
                    medium: 'https://example.com/audio/guzheng_medium.mp3',
                    high: 'https://example.com/audio/guzheng_high.mp3'
                },
                chimes: {
                    low: 'https://example.com/audio/chimes_low.mp3',
                    medium: 'https://example.com/audio/chimes_medium.mp3',
                    high: 'https://example.com/audio/chimes_high.mp3'
                }
            };
            
            // 音频缓冲区
            const audioBuffers = {
                piano: { low: null, medium: null, high: null },
                drum: { low: null, medium: null, high: null },
                guzheng: { low: null, medium: null, high: null },
                chimes: { low: null, medium: null, high: null }
            };
            
            // DOM元素
            const tempoControl = document.getElementById('tempo-control');
            const tempoValue = document.getElementById('tempo-value');
            const volumeControl = document.getElementById('volume-control');
            const volumeValue = document.getElementById('volume-value');
            const autoPlayToggle = document.getElementById('auto-play');
            const playBtn = document.getElementById('play-btn');
            const resetBtn = document.getElementById('reset-btn');
            const stressControls = document.querySelectorAll('.stress-control');
            const keyboardKeys = document.querySelectorAll('.keyboard-key');
            const poemChars = document.querySelectorAll('#poem-display span');
            const rhythmPatterns = document.querySelectorAll('.rhythm-pattern');
            const instrumentSelect = document.getElementById('instrument-select');
            
            // 音频上下文
            const AudioContext = window.AudioContext || window.webkitAudioContext;
            const audioContext = new AudioContext();
            
            // 节拍器变量
            let isPlaying = false;
            let currentCharIndex = 0;
            let timerID = null;
            let beatInterval = 60000 / rhythmData.tempo; // 毫秒
            
            // 加载音频资源
            function loadAudioAssets() {
                // 实际项目中应替换为真实音频加载逻辑
                console.log('加载音频资源...');
                
                // 这里仅为示例,实际应用中需要使用XMLHttpRequest或Fetch API加载音频
                // 并使用audioContext.decodeAudioData()解码音频数据
            }
            
            // 播放节奏音(使用音频样本)
            function playBeat(stressLevel) {
                // 恢复音频上下文(如果被浏览器暂停)
                if (audioContext.state === 'suspended') {
                    audioContext.resume();
                }
                
                // 根据乐器和重音级别选择音频
                const instrument = rhythmData.instrument;
                let audioBuffer;
                
                switch(stressLevel) {
                    case 0: // 弱
                        audioBuffer = audioBuffers[instrument].low;
                        break;
                    case 1: // 中
                        audioBuffer = audioBuffers[instrument].medium;
                        break;
                    case 2: // 强
                        audioBuffer = audioBuffers[instrument].high;
                        break;
                }
                
                // 如果有音频缓冲区,播放音频;否则使用振荡器
                if (audioBuffer) {
                    const source = audioContext.createBufferSource();
                    const gainNode = audioContext.createGain();
                    
                    gainNode.gain.setValueAtTime(rhythmData.volume / 100, audioContext.currentTime);
                    
                    source.buffer = audioBuffer;
                    source.connect(gainNode);
                    gainNode.connect(audioContext.destination);
                    source.start();
                } else {
                    // 回退到振荡器
                    const freq = stressLevel === 0 ? 220 : (stressLevel === 1 ? 330 : 440);
                    const vol = (stressLevel + 1) * (rhythmData.volume / 300);
                    
                    const oscillator = audioContext.createOscillator();
                    const gainNode = audioContext.createGain();
                    
                    oscillator.type = 'sine';
                    oscillator.frequency.setValueAtTime(freq, audioContext.currentTime);
                    
                    gainNode.gain.setValueAtTime(0, audioContext.currentTime);
                    gainNode.gain.linearRampToValueAtTime(vol, audioContext.currentTime + 0.01);
                    gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + 0.2);
                    
                    oscillator.connect(gainNode);
                    gainNode.connect(audioContext.destination);
                    
                    oscillator.start();
                    oscillator.stop(audioContext.currentTime + 0.2);
                }
            }
            
            // 更新界面显示
            function updateUI() {
                // 更新速度显示
                tempoValue.textContent = rhythmData.tempo;
                tempoControl.value = rhythmData.tempo;
                
                // 更新音量显示
                volumeValue.textContent = rhythmData.volume;
                volumeControl.value = rhythmData.volume;
                
                // 更新自动播放状态
                autoPlayToggle.checked = rhythmData.autoPlay;
                
                // 更新乐器选择
                instrumentSelect.value = rhythmData.instrument;
                
                // 更新重音显示
                stressControls.forEach((control, index) => {
                    const keyElement = control.querySelector('.keyboard-key');
                    const textElement = control.querySelector('span');
                    
                    switch(rhythmData.stress[index]) {
                        case 0: // 弱
                            keyElement.className = 'keyboard-key h-12 rounded-md bg-gray-200 flex items-center justify-center cursor-pointer mb-1';
                            textElement.textContent = '弱';
                            textElement.className = 'text-xs text-gray-500';
                            break;
                        case 1: // 中
                            keyElement.className = 'keyboard-key h-12 rounded-md bg-primary/60 flex items-center justify-center cursor-pointer mb-1';
                            textElement.textContent = '中';
                            textElement.className = 'text-xs text-primary';
                            break;
                        case 2: // 强
                            keyElement.className = 'keyboard-key h-12 rounded-md bg-secondary flex items-center justify-center cursor-pointer mb-1';
                            textElement.textContent = '强';
                            textElement.className = 'text-xs text-secondary';
                            break;
                    }
                });
                
                // 更新键盘显示
                keyboardKeys.forEach((key, index) => {
                    switch(rhythmData.stress[index]) {
                        case 0: // 弱
                            key.className = 'keyboard-key h-20 md:h-32 rounded-lg bg-gray-200 flex flex-col items-center justify-center cursor-pointer border-2 border-gray-300 hover:border-primary';
                            break;
                        case 1: // 中
                            key.className = 'keyboard-key h-20 md:h-32 rounded-lg bg-primary/60 flex flex-col items-center justify-center cursor-pointer border-2 border-primary/80 hover:border-primary';
                            break;
                        case 2: // 强
                            key.className = 'keyboard-key h-20 md:h-32 rounded-lg bg-secondary flex flex-col items-center justify-center cursor-pointer border-2 border-secondary/80 hover:border-primary';
                            break;
                    }
                });
                
                // 更新预设模式高亮
                document.querySelectorAll('.rhythm-pattern').forEach((pattern, index) => {
                    if (index + 1 === rhythmData.currentPattern) {
                        pattern.className = 'p-4 border-2 border-primary rounded-lg bg-primary/10 cursor-pointer rhythm-pattern';
                    } else {
                        pattern.className = 'p-4 border-2 border-gray-200 rounded-lg hover:border-primary transition-colors duration-200 cursor-pointer rhythm-pattern';
                    }
                });
            }
            
            // 高亮当前字符
            function highlightChar(index) {
                // 重置所有字符样式
                poemChars.forEach((char, i) => {
                    if (i === index) {
                        // 根据重音级别设置不同的高亮效果
                        switch(rhythmData.stress[index]) {
                            case 0: // 弱
                                char.className = 'inline-block px-2 py-1 mx-1 bg-gray-100 rounded animate-pulse';
                                break;
                            case 1: // 中
                                char.className = 'inline-block px-2 py-1 mx-1 bg-primary/20 rounded animate-pulse';
                                break;
                            case 2: // 强
                                char.className = 'inline-block px-2 py-1 mx-1 bg-secondary/30 rounded animate-beat';
                                break;
                        }
                    } else {
                        char.className = 'inline-block px-2 py-1 mx-1';
                    }
                });
            }
            
            // 播放下一个字符
            function playNextChar() {
                playBeat(rhythmData.stress[currentCharIndex]);
                highlightChar(currentCharIndex);
                
                currentCharIndex = (currentCharIndex + 1) % poemChars.length;
                
                if (isPlaying && rhythmData.autoPlay) {
                    timerID = setTimeout(playNextChar, beatInterval);
                }
            }
            
            // 开始/停止播放
            function togglePlay() {
                if (isPlaying) {
                    // 停止播放
                    isPlaying = false;
                    clearTimeout(timerID);
                    playBtn.innerHTML = '<i class="fa fa-play mr-2"></i> 播放';
                } else {
                    // 开始播放
                    isPlaying = true;
                    currentCharIndex = 0;
                    beatInterval = 60000 / rhythmData.tempo;
                    playNextChar();
                    playBtn.innerHTML = '<i class="fa fa-stop mr-2"></i> 停止';
                }
            }
            
            // 重置所有设置
            function resetAll() {
                // 停止播放
                if (isPlaying) {
                    togglePlay();
                }
                
                // 重置节奏数据
                rhythmData.stress = [0, 1, 0, 2, 0, 1, 2];
                rhythmData.tempo = 80;
                rhythmData.volume = 70;
                rhythmData.autoPlay = false;
                rhythmData.currentPattern = 1;
                rhythmData.instrument = 'piano';
                
                // 更新UI
                updateUI();
                
                // 重置字符高亮
                poemChars.forEach(char => {
                    char.className = 'inline-block px-2 py-1 mx-1';
                });
            }
            
            // 点击字符设置重音
            stressControls.forEach(control => {
                control.addEventListener('click', () => {
                    const index = parseInt(control.getAttribute('data-char')) - 1;
                    
                    // 循环切换重音级别:弱 -> 中 -> 强 -> 弱
                    rhythmData.stress[index] = (rhythmData.stress[index] + 1) % 3;
                    
                    // 更新UI
                    updateUI();
                });
            });
            
            // 键盘点击事件
            keyboardKeys.forEach(key => {
                key.addEventListener('click', () => {
                    const index = parseInt(key.getAttribute('data-key')) - 1;
                    
                    // 播放对应重音的节拍
                    playBeat(rhythmData.stress[index]);
                    
                    // 高亮对应字符
                    highlightChar(index);
                    
                    // 如果不是自动播放模式,点击后重置高亮
                    if (!rhythmData.autoPlay) {
                        setTimeout(() => {
                            poemChars.forEach((char, i) => {
                                if (i !== index) return;
                                char.className = 'inline-block px-2 py-1 mx-1';
                            });
                        }, 300);
                    }
                });
            });
            
            // 键盘按键事件
            document.addEventListener('keydown', (e) => {
                // 防止按键触发页面滚动
                if (['A', 'S', 'D', 'F', 'G', 'H', 'J'].includes(e.key.toUpperCase())) {
                    e.preventDefault();
                }
                
                // 映射键盘按键到字符
                const keyMap = {
                    'A': 1, 'S': 2, 'D': 3, 'F': 4, 
                    'G': 5, 'H': 6, 'J': 7
                };
                
                if (keyMap[e.key.toUpperCase()]) {
                    const index = keyMap[e.key.toUpperCase()] - 1;
                    
                    // 播放对应重音的节拍
                    playBeat(rhythmData.stress[index]);
                    
                    // 高亮对应字符
                    highlightChar(index);
                    
                    // 高亮键盘按键
                    keyboardKeys[index].classList.add('active');
                    
                    // 如果不是自动播放模式,点击后重置高亮
                    if (!rhythmData.autoPlay) {
                        setTimeout(() => {
                            poemChars.forEach((char, i) => {
                                if (i !== index) return;
                                char.className = 'inline-block px-2 py-1 mx-1';
                            });
                            keyboardKeys[index].classList.remove('active');
                        }, 300);
                    }
                }
            });
            
            // 释放键盘按键
            document.addEventListener('keyup', (e) => {
                const keyMap = {
                    'A': 1, 'S': 2, 'D': 3, 'F': 4, 
                    'G': 5, 'H': 6, 'J': 7
                };
                
                if (keyMap[e.key.toUpperCase()]) {
                    const index = keyMap[e.key.toUpperCase()] - 1;
                    keyboardKeys[index].classList.remove('active');
                }
            });
            
            // 速度控制
            tempoControl.addEventListener('input', () => {
                rhythmData.tempo = parseInt(tempoControl.value);
                tempoValue.textContent = rhythmData.tempo;
                
                // 如果正在播放,更新节拍间隔
                if (isPlaying && rhythmData.autoPlay) {
                    clearTimeout(timerID);
                    beatInterval = 60000 / rhythmData.tempo;
                    timerID = setTimeout(playNextChar, beatInterval);
                }
            });
            
            // 音量控制
            volumeControl.addEventListener('input', () => {
                rhythmData.volume = parseInt(volumeControl.value);
                volumeValue.textContent = rhythmData.volume;
            });
            
            // 自动播放切换
            autoPlayToggle.addEventListener('change', () => {
                rhythmData.autoPlay = autoPlayToggle.checked;
                
                // 如果开启自动播放且当前没有播放,则开始播放
                if (rhythmData.autoPlay && !isPlaying) {
                    togglePlay();
                }
            });
            
            // 播放按钮
            playBtn.addEventListener('click', togglePlay);
            
            // 重置按钮
            resetBtn.addEventListener('click', resetAll);
            
            // 预设节奏模式
            document.querySelectorAll('.rhythm-pattern').forEach((pattern, index) => {
                pattern.addEventListener('click', () => {
                    rhythmData.currentPattern = index + 1;
                    rhythmData.stress = rhythmPatterns[index].stress;
                    
                    // 更新UI
                    updateUI();
                });
            });
            
            // 乐器选择
            instrumentSelect.addEventListener('change', () => {
                rhythmData.instrument = instrumentSelect.value;
                console.log(`已切换乐器: ${rhythmData.instrument}`);
            });
            
            // 加载音频资源
            loadAudioAssets();
            
            // 初始化UI
            updateUI();
        });
    </script>
</body>
</html>

        
编辑器加载中
预览
控制台