闲来无事,用HTML+CSS+JS打造一个84键机械键盘模拟器

今天闲来无聊,突发奇想要用前端技术模拟一个机械键盘。说干就干,花了点时间搞出来了这么一个有模有样的84键机械键盘模拟器。来看看效果吧!

升级版的模拟器

屏幕录制 2025-04-18 155308

是不是挺像那么回事的?哈哈!

它来源于我的实体键盘:

有需要自取哈别忘了点个赞!

代码:

bash 复制代码
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>84键机械键盘精确复刻</title>
    <style>
        body {
            background: #f5f5f5;
            display: flex;
            justify-content: center;
            padding: 20px;
            font-family: 'Segoe UI', sans-serif;
        }

        .keyboard {
            display: grid;
            grid-template-columns: repeat(16, 42px);
            gap: 3px;
            background: #333;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
        }

        .key {
            background: #222;
            color: white;
            border: 1px solid #444;
            border-radius: 4px;
            padding: 6px;
            min-height: 42px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            text-align: center;
            font-size: 12px;
            line-height: 1.3;
            cursor: pointer;
            transition: all 0.1s ease;
            user-select: none;
        }

        .arrow {
            font-size: 22px
        }

        /* 特殊键位跨度 */
        .span2 {
            grid-column: span 2;
        }

        .span3 {
            grid-column: span 3;
        }

        .span4 {
            grid-column: span 4;
        }

        .span5 {
            grid-column: span 5;
        }

        /* 颜色系统 */
        .esc {
            background: #00ffff;
            color: #000;
        }

        .enter {
            background: #ffa500;
        }

        .space {
            background: #0066cc;
        }

        .special {
            background: #444;
        }

        /* 复合字符 */
        .sub-char {
            font-size: 9px;
            color: #aaa;
            line-height: 1.1;
            margin-top: 2px;
        }

        /* 按压效果 */
        .key:active {
            transform: translateY(2px);
            background: #2a2a2a;
            box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.2);
        }
        .key.pressed {
            transform: translateY(2px);
            background: #2a2a2a;
            box-shadow: inset 0 2px 3px rgba(0, 0, 0, 0.2);
        }
    </style>
</head>
<body>
<div class="keyboard">
    <!-- 第1行 -->
    <div class="key esc" data-key="Escape">ESC</div>
    <div class="key" data-key="F1">F1</div>
    <div class="key" data-key="F2">F2</div>
    <div class="key" data-key="F3">F3</div>
    <div class="key" data-key="F4">F4</div>
    <div class="key" data-key="F5">F5</div>
    <div class="key" data-key="F6">F6</div>
    <div class="key" data-key="F7">F7</div>
    <div class="key" data-key="F8">F8</div>
    <div class="key" data-key="F9">F9</div>
    <div class="key" data-key="F10">F10</div>
    <div class="key" data-key="F11">F11</div>
    <div class="key" data-key="F12">F12</div>
    <div class="key" data-key="PrintScreen">PrtSc</div>
    <div class="key" data-key="Insert">Ins</div>
    <div class="key" data-key="Home">Home</div>

    <!-- 第2行 -->
    <div class="key" data-key="`">~<br><span class="sub-char">`</span></div>
    <div class="key" data-key="1">!<br><span class="sub-char">1</span></div>
    <div class="key" data-key="2">@<br><span class="sub-char">2</span></div>
    <div class="key" data-key="3">#<br><span class="sub-char">3</span></div>
    <div class="key" data-key="4">$<br><span class="sub-char">4</span></div>
    <div class="key" data-key="5">%<br><span class="sub-char">5</span></div>
    <div class="key" data-key="6">^<br><span class="sub-char">6</span></div>
    <div class="key" data-key="7">&<br><span class="sub-char">7</span></div>
    <div class="key" data-key="8">*<br><span class="sub-char">8</span></div>
    <div class="key" data-key="9">(<br><span class="sub-char">9</span></div>
    <div class="key" data-key="0">)<br><span class="sub-char">0</span></div>
    <div class="key span4" data-key="Backspace">⇐Back</div>
    <div class="key" data-key="Delete">Del</div>

    <!-- 第3行 -->
    <div class="key span2" data-key="Tab">Tab↹</div>
    <div class="key" data-key="q">Q</div>
    <div class="key" data-key="w">W</div>
    <div class="key" data-key="e">E</div>
    <div class="key" data-key="r">R</div>
    <div class="key" data-key="t">T</div>
    <div class="key" data-key="y">Y</div>
    <div class="key" data-key="u">U</div>
    <div class="key" data-key="i">I</div>
    <div class="key" data-key="o">O</div>
    <div class="key" data-key="p">P</div>
    <div class="key" data-key="[">{<br><span class="sub-char">[</span></div>
    <div class="key" data-key="]">}<br><span class="sub-char">]</span></div>
    <div class="key" data-key="\">|<br><span class="sub-char">\</span></div>
    <div class="key" data-key="PageUp">PgUp</div>

    <!-- 第4行 -->
    <div class="key" data-key="CapsLock">Caps</div>
    <div class="key" data-key="a">A</div>
    <div class="key" data-key="s">S</div>
    <div class="key" data-key="d">D</div>
    <div class="key" data-key="f">F</div>
    <div class="key" data-key="g">G</div>
    <div class="key" data-key="h">H</div>
    <div class="key" data-key="j">J</div>
    <div class="key" data-key="k">K</div>
    <div class="key" data-key="l">L</div>
    <div class="key" data-key=";">:<br><span class="sub-char">;</span></div>
    <div class="key" data-key="'">"<br><span class="sub-char">'</span></div>
    <div class="key enter span3" data-key="Enter">Enter</div>
    <div class="key" data-key="PageDown">PgDn</div>

    <!-- 第5行 -->
    <div class="key span2" data-key="ShiftLeft">⇧Shift</div>
    <div class="key" data-key="z">Z</div>
    <div class="key" data-key="x">X</div>
    <div class="key" data-key="c">C</div>
    <div class="key" data-key="v">V</div>
    <div class="key" data-key="b">B</div>
    <div class="key" data-key="n">N</div>
    <div class="key" data-key="m">M</div>
    <div class="key" data-key=",">&lt;<br><span class="sub-char">,</span></div>
    <div class="key" data-key=".">><br><span class="sub-char">.</span></div>
    <div class="key" data-key="/">?<br><span class="sub-char">/</span></div>
    <div class="key span2" data-key="ShiftRight">⇧Shift</div>
    <div class="key arrow" data-key="ArrowUp">△</div>
    <div class="key" data-key="End">End</div>

    <!-- 第6行 -->
    <div class="key span2" data-key="ControlLeft">Ctrl<br><span class="sub-char">Control</span></div>
    <div class="key" data-key="MetaLeft">Win<br><span class="sub-char">Option</span></div>
    <div class="key span2" data-key="AltLeft">Alt<br><span class="sub-char">Cmd</span></div>
    <div class="key space span5" data-key=" ">Space</div>
    <div class="key" data-key="AltRight">Alt<br><span class="sub-char">Cmd</span></div>
    <div class="key" data-key="Fn">Fn</div>
    <div class="key" data-key="ControlRight">Ctrl<br><span class="sub-char">Control</span></div>
    <div class="key" data-key="ArrowLeft">◁</div>
    <div class="key arrow" data-key="ArrowDown">▽</div>
    <div class="key" data-key="ArrowRight">▷</div>
</div>

<script>
    document.addEventListener('keydown', function(event) {
        const key = event.key.toLowerCase();
        const keyElement = document.querySelector(`.key:not(.span2):not(.span3):not(.span4):not(.span5):not(.arrow):not(.special)[data-key="${key}"]`);
        if (keyElement) {
            keyElement.classList.add('pressed');
        }
    });

    document.addEventListener('keyup', function(event) {
        const key = event.key.toLowerCase();
        const keyElement = document.querySelector(`.key:not(.span2):not(.span3):not(.span4):not(.span5):not(.arrow):not(.special)[data-key="${key}"]`);
        if (keyElement) {
            keyElement.classList.remove('pressed');
        }
    });
</script>
</body>
</html>
相关推荐
一晌小贪欢15 小时前
【Html模板】电商运营可视化大屏模板 Excel存储 + 一键导出(已上线-可预览)
前端·数据分析·html·excel·数据看板·电商大屏·大屏看板
街尾杂货店&16 小时前
css - 实现三角形 div 容器,用css画一个三角形(提供示例源码)简单粗暴几行代码搞定!
前端·css
顺凡16 小时前
删一个却少俩:Antd Tag 多节点同时消失的原因
前端·javascript·面试
小白路过16 小时前
CSS transform矩阵变换全面解析
前端·css·矩阵
前端大卫16 小时前
动态监听DOM元素高度变化
前端·javascript
Cxiaomu17 小时前
React Native App 图表绘制完整实现指南
javascript·react native·react.js
qq. 280403398417 小时前
vue介绍
前端·javascript·vue.js
Mr.Jessy17 小时前
Web APIs 学习第五天:日期对象与DOM节点
开发语言·前端·javascript·学习·html
Hi~晴天大圣18 小时前
HTML onclick用法
前端·html
速易达网络18 小时前
HTML<output>标签
javascript·css·css3