jym,实现一个弹钢琴

76 阅读1分钟

钢琴.png

<!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: url('https://pic.52112.com/180308/180308_53/hzCkqdEfYX_small.jpg') 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">
        <!-- White keys -->
        <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>