钢琴键盘特效

<!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>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值