<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>钢琴键盘特效</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to bottom, #1a1a2e, #16213e);
font-family: Arial, sans-serif;
overflow-x: hidden;
}
.piano-container {
display: flex;
position: relative;
margin: 40px 0;
}
/* 白键样式 */
.white-key {
width: 60px;
height: 250px;
background: #fff;
border: 1px solid #ccc;
border-radius: 0 0 5px 5px;
cursor: pointer;
position: relative;
z-index: 1;
box-shadow: 0 5px 10px rgba(0,0,0,0.2);
transition: all 0.1s;
}
.white-key:hover {
background: #f0f0f0;
}
.white-key.active {
background: #ddd;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
transform: translateY(2px);
}
/* 黑键样式 */
.black-key {
width: 36px;
height: 150px;
background: linear-gradient(to bottom, #333, #000);
border-radius: 0 0 5px 5px;
position: absolute;
z-index: 2;
cursor: pointer;
box-shadow: 0 5px 10px rgba(0,0,0,0.4);
transition: all 0.1s;
}
.black-key:hover {
background: linear-gradient(to bottom, #222, #000);
}
.black-key.active {
background: linear-gradient(to bottom, #111, #000);
box-shadow: 0 2px 5px rgba(0,0,0,0.4);
transform: translateY(2px);
}
/* 黑键位置 */
.black-key:nth-child(1) { left: 45px; }
.black-key:nth-child(2) { left: 105px; }
.black-key:nth-child(3) { left: 225px; }
.black-key:nth-child(4) { left: 285px; }
.black-key:nth-child(5) { left: 345px; }
/* 键盘标签 */
.key-label {
position: absolute;
bottom: 10px;
width: 100%;
text-align: center;
font-size: 14px;
color: #333;
user-select: none;
}
.black-key .key-label {
color: #fff;
}
/* 标题样式 */
.title {
color: #fff;
text-shadow: 0 0 10px rgba(255,255,255,0.5);
margin-bottom: 30px;
}
/* 底部链接 */
.footer-link {
margin-top: 40px;
color: rgba(255,255,255,0.7);
text-decoration: none;
font-size: 14px;
transition: all 0.3s;
}
.footer-link:hover {
color: #fff;
text-shadow: 0 0 10px rgba(255,255,255,0.5);
}
/* 响应式设计 */
@media (max-width: 768px) {
.white-key {
width: 40px;
height: 180px;
}
.black-key {
width: 24px;
height: 100px;
}
.black-key:nth-child(1) { left: 30px; }
.black-key:nth-child(2) { left: 70px; }
.black-key:nth-child(3) { left: 150px; }
.black-key:nth-child(4) { left: 190px; }
.black-key:nth-child(5) { left: 230px; }
.key-label {
font-size: 10px;
}
}
</style>
</head>
<body>
<h1 class="title">HTML5 钢琴键盘特效</h1>
<div class="piano-container">
<!-- 白键 -->
<div class="white-key" data-note="C">
<span class="key-label">C</span>
</div>
<div class="white-key" data-note="D">
<span class="key-label">D</span>
</div>
<div class="white-key" data-note="E">
<span class="key-label">E</span>
</div>
<div class="white-key" data-note="F">
<span class="key-label">F</span>
</div>
<div class="white-key" data-note="G">
<span class="key-label">G</span>
</div>
<div class="white-key" data-note="A">
<span class="key-label">A</span>
</div>
<div class="white-key" data-note="B">
<span class="key-label">B</span>
</div>
<!-- 黑键 -->
<div class="black-key" data-note="C#">
<span class="key-label">C#</span>
</div>
<div class="black-key" data-note="D#">
<span class="key-label">D#</span>
</div>
<div class="black-key" data-note="F#">
<span class="key-label">F#</span>
</div>
<div class="black-key" data-note="G#">
<span class="key-label">G#</span>
</div>
<div class="black-key" data-note="A#">
<span class="key-label">A#</span>
</div>
</div>
<script>
// 音频上下文
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
// 获取所有琴键
const keys = document.querySelectorAll('.white-key, .black-key');
// 音符频率映射
const noteFrequencies = {
'C': 261.63, 'C#': 277.18,
'D': 293.66, 'D#': 311.13,
'E': 329.63,
'F': 349.23, 'F#': 369.99,
'G': 392.00, 'G#': 415.30,
'A': 440.00, 'A#': 466.16,
'B': 493.88
};
// 为每个琴键添加事件监听
keys.forEach(key => {
// 鼠标按下
key.addEventListener('mousedown', () => {
playNote(key.dataset.note);
key.classList.add('active');
});
// 鼠标释放
key.addEventListener('mouseup', () => {
key.classList.remove('active');
});
// 鼠标移出
key.addEventListener('mouseleave', () => {
key.classList.remove('active');
});
// 触摸事件
key.addEventListener('touchstart', (e) => {
e.preventDefault();
playNote(key.dataset.note);
key.classList.add('active');
});
key.addEventListener('touchend', () => {
key.classList.remove('active');
});
});
// 键盘事件监听
document.addEventListener('keydown', (e) => {
const keyMap = {
'a': 'C', 'w': 'C#',
's': 'D', 'e': 'D#',
'd': 'E',
'f': 'F', 't': 'F#',
'g': 'G', 'y': 'G#',
'h': 'A', 'u': 'A#',
'j': 'B'
};
if (keyMap[e.key]) {
const note = keyMap[e.key];
const keyElement = document.querySelector(`[data-note="${note}"]`);
if (keyElement) {
playNote(note);
keyElement.classList.add('active');
}
}
});
document.addEventListener('keyup', (e) => {
const keyMap = {
'a': 'C', 'w': 'C#',
's': 'D', 'e': 'D#',
'd': 'E',
'f': 'F', 't': 'F#',
'g': 'G', 'y': 'G#',
'h': 'A', 'u': 'A#',
'j': 'B'
};
if (keyMap[e.key]) {
const note = keyMap[e.key];
const keyElement = document.querySelector(`[data-note="${note}"]`);
if (keyElement) {
keyElement.classList.remove('active');
}
}
});
// 播放音符函数
function playNote(note) {
const frequency = noteFrequencies[note];
if (!frequency) return;
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.type = 'sine';
oscillator.frequency.value = frequency;
gainNode.gain.value = 0.3;
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start();
// 0.5秒后淡出停止
gainNode.gain.exponentialRampToValueAtTime(
0.01,
audioContext.currentTime + 0.5
);
oscillator.stop(audioContext.currentTime + 0.5);
}
</script>
</body>
</html>
589

被折叠的 条评论
为什么被折叠?



