<!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>
index.html
index.html