<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5钢琴键盘特效</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(to bottom, #1a1a2e, #16213e);
font-family: 'Arial', sans-serif;
flex-direction: column;
padding: 20px;
}
h1 {
color: #fff;
margin-bottom: 30px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
.piano-container {
display: flex;
position: relative;
margin-bottom: 50px;
}
.key {
cursor: pointer;
position: relative;
display: flex;
justify-content: center;
align-items: flex-end;
padding-bottom: 20px;
font-weight: bold;
user-select: none;
}
.white-key {
width: 60px;
height: 200px;
background: linear-gradient(to bottom, #fff 0%, #f5f5f5 100%);
border: 1px solid #ccc;
border-radius: 0 0 5px 5px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
color: #333;
z-index: 1;
transition: all 0.1s;
}
.white-key.active {
background: linear-gradient(to bottom, #e0e0e0 0%, #d5d5d5 100%);
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
transform: translateY(3px);
}
.black-key {
width: 36px;
height: 120px;
background: linear-gradient(to bottom, #333 0%, #000 100%);
border-radius: 0 0 5px 5px;
margin-left: -18px;
margin-right: -18px;
z-index: 2;
color: #fff;
transition: all 0.1s;
}
.black-key.active {
background: linear-gradient(to bottom, #222 0%, #111 100%);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
transform: translateY(2px);
}
.key-label {
pointer-events: none;
}
.link {
margin-top: 30px;
}
.link a {
color: #fff;
background: rgba(255, 255, 255, 0.2);
padding: 10px 20px;
border-radius: 30px;
text-decoration: none;
font-weight: bold;
transition: all 0.3s;
}
.link a:hover {
background: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 15px rgba(255, 255, 255, 0.2);
}
.instructions {
color: #fff;
margin-top: 20px;
text-align: center;
opacity: 0.7;
}
</style>
</head>
<body>
<h1>HTML5钢琴键盘特效</h1>
<div class="piano-container">
<!-- 白键 -->
<div class="key white-key" data-note="C">
<span class="key-label">C</span>
</div>
<div class="key white-key" data-note="D">
<span class="key-label">D</span>
</div>
<div class="key white-key" data-note="E">
<span class="key-label">E</span>
</div>
<div class="key white-key" data-note="F">
<span class="key-label">F</span>
</div>
<div class="key white-key" data-note="G">
<span class="key-label">G</span>
</div>
<div class="key white-key" data-note="A">
<span class="key-label">A</span>
</div>
<div class="key white-key" data-note="B">
<span class="key-label">B</span>
</div>
<!-- 黑键 -->
<div class="key black-key" data-note="C#">
<span class="key-label">C#</span>
</div>
<div class="key black-key" data-note="D#">
<span class="key-label">D#</span>
</div>
<div class="key black-key" data-note="F#">
<span class="key-label">F#</span>
</div>
<div class="key black-key" data-note="G#">
<span class="key-label">G#</span>
</div>
<div class="key black-key" data-note="A#">
<span class="key-label">A#</span>
</div>
</div>
<p class="instructions">点击键盘或按键盘上的A,S,D,F,G,H,J键演奏</p>
<div class="link">
<a href="http://2sf.100wanfu.com" target="_blank">访问示例网站</a>
</div>
<script>
// 键盘按键映射
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'
};
// 音频上下文
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
// 获取所有琴键
const keys = document.querySelectorAll('.key');
// 鼠标点击事件
keys.forEach(key => {
key.addEventListener('mousedown', () => playNote(key));
key.addEventListener('mouseup', () => stopNote(key));
key.addEventListener('mouseleave', () => stopNote(key));
});
// 键盘事件
document.addEventListener('keydown', (e) => {
const note = keyMap[e.key.toLowerCase()];
if (note) {
const key = document.querySelector(`.key[data-note="${note}"]`);
if (key) {
key.classList.add('active');
playNote(key);
}
}
});
document.addEventListener('keyup', (e) => {
const note = keyMap[e.key.toLowerCase()];
if (note) {
const key = document.querySelector(`.key[data-note="${note}"]`);
if (key) {
key.classList.remove('active');
stopNote(key);
}
}
});
// 播放音符
function playNote(key) {
if (!key.classList.contains('active')) {
key.classList.add('active');
const note = key.getAttribute('data-note');
const frequency = getFrequency(note);
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();
key.oscillator = oscillator;
key.gainNode = gainNode;
}
}
// 停止音符
function stopNote(key) {
if (key.classList.contains('active')) {
key.classList.remove('active');
if (key.gainNode) {
key.gainNode.gain.exponentialRampToValueAtTime(
0.001,
audioContext.currentTime + 0.1
);
if (key.oscillator) {
setTimeout(() => {
key.oscillator.stop();
key.oscillator.disconnect();
key.gainNode.disconnect();
}, 100);
}
}
}
}
// 获取音符频率
function getFrequency(note) {
const notes = {
'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
};
return notes[note] || 440;
}
</script>
</body>
</html>