
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>钢琴</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
background: url('https://ts1.cn.mm.bing.net/th/id/R-C.497dcc2e07eef223b57f5bed66730704?rik=M29gwOPOCgUNnA&riu=http%3a%2f%2fimg.sytuku.com%2fuptu%2fyulantu%2f161010%2f5-1610101A258.jpg&ehk=42Y6geS1M2lOeU6eBXfx3CHlsivDIlMvn1xNXuM2t1E%3d&risl=&pid=ImgRaw&r=0') no-repeat center center fixed;
background-size: 100% auto;
margin: 0;
padding: 20px;
perspective: 1000px;
}
.piano {
display: flex;
position: relative;
margin-top: 50px;
white-space: nowrap;
background: #000;
border-radius: 10px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.7);
transform-style: preserve-3d;
transform: rotateX(10deg) rotateY(0deg);
}
.white-key {
height: 120px;
width: 60px;
background: #fff;
border: 1px solid #ccc;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
position: relative;
cursor: pointer;
display: inline-block;
transform: rotateX(0deg);
transform-style: preserve-3d;
transition: transform 0.1s, box-shadow 0.1s;
}
.white-key:active,
.white-key.active {
transform: translateY(4px) rotateX(10deg);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.6);
}
.white-key:nth-of-type(1) {
margin-right: -1px;
}
.white-key:nth-of-type(2) {
margin-right: -1px;
}
.white-key:nth-of-type(3) {
margin-right: -1px;
}
.white-key:nth-of-type(4) {
margin-right: -1px;
}
.white-key:nth-of-type(5) {
margin-right: -1px;
}
.white-key:nth-of-type(6) {
margin-right: -1px;
}
.white-key:nth-of-type(7) {
margin-right: -1px;
}
.white-key:nth-of-type(8) {
margin-right: -1px;
}
</style>
</head>
<body>
<div id="types">
音调类型:
<button onclick="setType(0)">sine</button>
<button onclick="setType(1)">square</button>
<button onclick="setType(2)">sawtooth</button>
<button onclick="setType(3)">triangle</button>
<span id="selType">square</span>
</div>
<div class="piano">
<div class="white-key" id="key-d" onclick="create(293.66)">d</div>
<div class="white-key" id="key-e" onclick="create(329.63)">e</div>
<div class="white-key" id="key-f" onclick="create(349.23)">f</div>
<div class="white-key" id="key-g" onclick="create(392.00)">g</div>
<div class="white-key" id="key-h" onclick="create(440.00)">h</div>
<div class="white-key" id="key-a" onclick="create(493.88)">a</div>
<div class="white-key" id="key-b" onclick="create(523.26)">b</div>
<div class="white-key" id="key-c" onclick="create(587.33)">c</div>
</div>
<script>
const audioTypeList = ['sine', 'square', 'sawtooth', 'triangle'];
let typeIndex = 1;
function setType(i) {
typeIndex = i;
document.getElementById('selType').innerHTML = audioTypeList[i];
}
function create(frequency) {
const volBl = 0.1;
const audioCtx = new AudioContext();
const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.type = audioTypeList[typeIndex];
oscillator.frequency.value = frequency;
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
gainNode.gain.linearRampToValueAtTime(1 * volBl, audioCtx.currentTime + 0.01);
oscillator.start(audioCtx.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.1 * volBl, audioCtx.currentTime + 1);
oscillator.stop(audioCtx.currentTime + 1);
}
document.addEventListener('keydown', function(event) {
const keyMap = {
'd': 293.66,
'e': 329.63,
'f': 349.23,
'g': 392.00,
'h': 440.00,
'a': 493.88,
'b': 523.26,
'c': 587.33
};
const frequency = keyMap[event.key.toLowerCase()];
if (frequency) {
create(frequency);
const keyElement = document.getElementById('key-' + event.key.toLowerCase());
keyElement.classList.add('active');
setTimeout(() => keyElement.classList.remove('active'), 200);
}
});
</script>
</body>
</html>