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

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

屏幕录制 2025-04-18 155308

是不是挺像那么回事的?哈哈!
它来源于我的实体键盘:
照片

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

代码:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/902131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智慧城市:如同为城市装上智能大脑,开启智慧生活

智慧城市的概念随着信息技术的飞速发展而逐渐兴起&#xff0c;它通过集成物联网、大数据、人工智能和数字孪生等先进技术&#xff0c;为城市管理和居民生活带来了前所未有的智能化变革。本文将深入探讨这些核心技术及其在智慧城市的典型应用场景&#xff0c;展示智慧城市如何提…

科技快讯 | 智谱开源最新GLM模型系列;“AI 洗头店”现身广州;ChatGPT上线图库功能

智谱开源最新GLM模型系列&#xff0c;启用全球域名“Z.ai” 4月15日&#xff0c;智谱开源最新GLM模型系列&#xff0c;包括32B和9B尺寸&#xff0c;涵盖基座、推理、沉思三类模型&#xff0c;全部遵循MIT开源许可协议。推理模型GLM-Z1-32B-0414实测推理速度达200 tokens/秒&…

第32讲:卫星遥感与深度学习融合 —— 让地球“读懂”算法的语言

目录 🔍 一、讲讲“遥感+深度学习”到底是干啥的? ✅ 能解决什么问题? 🧠 二、基础原理串讲:深度学习如何“看懂”遥感图? 🛰 遥感图像数据类型: 🧠 CNN的基本思路: 🧪 三、实战案例:用CNN对遥感图像做地类分类 📦 所需R包: 🗂️ 步骤一:构建训…

【多线程5】面试常考锁知识点

文章目录 悲观/乐观锁挂起等待锁/自旋锁偏向锁轻量级/重量级锁锁升级CASCAS引发的ABA问题解决方案 原子类 公平/不公平锁可重入锁ReentrantLock读写锁 Callable接口 这里的“悲观”“乐观”“挂起等待”“自旋”“轻量级”“重量级”“公平”“非公平”“可重入”仅代表某个锁的…

第三届世界科学智能大赛新能源赛道:新能源发电功率预测-数据处理心得体会1

看懂数据 比赛数据说明&#xff1a; 文档&#xff08;报名之后可以下载&#xff09;大小操作初赛测试集.zip94MB下载初赛训练集.zip632MB下载output.zip145KB下载 任务和主题 AI新能源功率预报&#xff1a;根据历史发电功率数据和对应时段多类别气象预测数据&#xff0c;实…

【云馨AI-大模型】2025年4月第三周AI领域全景观察:硬件革命、生态博弈与国产化突围

一、硬件算力突破点燃多智能体时代 谷歌在4月12日Cloud Next大会发布第七代TPU Ironwood&#xff0c;单芯片算力达4614 TFLOPs&#xff0c;较前代内存提升6倍&#xff0c;专为AI推理场景优化。配合发布的Gemini 2.5 Flash模型通过"思考"功能实现成本优化&#xff0c…

第3章 垃圾收集器与内存分配策略《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》

第3章 垃圾收集器与内存分配策略 3.2 对象已死 Java世界中的所有对象实例&#xff0c;垃圾收集器进行回收前就是确定对象哪些是活着的&#xff0c;哪些已经死去。 3.2.1 引用计数算法 常见的回答是&#xff1a;给对象中添加一个引用计数器&#xff0c;有地方引用&#xff0…

超详细VMware虚拟机扩容磁盘容量-无坑版

1.环境&#xff1a; 虚拟机&#xff1a;VMware Workstation 17 Pro-17.5.2 Linux系统&#xff1a;Ubuntu 22.04 LTS 2.硬盘容量 虚拟机当前硬盘容量180G -> 扩展至 300G 3.操作步骤 &#xff08;1&#xff09;在虚拟机关机的状态下&#xff0c;虚拟机硬盘扩容之前必…

HarmonyOS:1.4 - HarmonyOS应用程序框架基础

判断题 1.在基于Stage模型开发的应用项目中都存在一个app.json5配置文件、以及一个或多个module.json5配置文件。 正确(True) 2.一个应用只可以包含一个UIAbility组件。 错误(False) 3.Background状态在UIAbility实例销毁时触发。可以在onDestroy()回调中进行系统资源的释…

HTTP HTTPS RSA

推荐阅读 小林coding HTTP篇 文章目录 HTTP 80HTTP 响应码1xx&#xff1a;信息性状态码&#xff08;Informational&#xff09;2xx&#xff1a;成功状态码&#xff08;Success&#xff09;3xx&#xff1a;重定向状态码&#xff08;Redirection&#xff09;4xx&#xff1a;客户端…

ORACLE数据库转国产阿里OceanBase数据库

1.BLOB类型修改 将接口内oracle.sql.BLOB改为java.sql.Blob 2.REGEXP_LIKE 判断函数正则表达式中字符转义问题 OB的正则表达式使用的是标准的Linux模式,oracle是黑盒子,在处理部分转义符([])的时候, Oracle无需使用转义符,OB务必使用转义符,加/转义处理,例如在regexp_like(t…

STM32的三种启动方式

目录 一、从主闪存存储器启动&#xff08;Main Flash Memory&#xff09; 二、从系统存储器启动&#xff08;System Memory&#xff09; 三、从内置SRAM启动&#xff08;Embedded SRAM&#xff09; 一、从主闪存存储器启动&#xff08;Main Flash Memory&#xff09; >&g…

Flutter使用flutter_driver进行自动化测试

Flutter自动化测试实践指南 作为一名iOS开发者&#xff0c;我最近对Flutter的自动化测试产生了浓厚兴趣。在开发过程中&#xff0c;我发现自动化测试对于保证应用质量至关重要&#xff0c;特别是像我们这样的创业团队&#xff0c;测试资源有限的情况下。 搭建Flutter自动化测…

Halcon应用:九点标定-手眼标定

提示&#xff1a;若没有查找的算子&#xff0c;可以评论区留言&#xff0c;会尽快更新 Halcon应用&#xff1a;九点标定-手眼标定 前言一、Halcon应用&#xff1f;二、应用实战1、图形理解[eye-to-hand]&#xff1a;1.1、开始应用2、 图形理解[eye-in-hand]2.1、 开始应用 前言…

【C++11】列表初始化、右值引用、完美转发、lambda表达式

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f310; C 语言 上篇文章&#xff1a;unordered_map、unordered_set底层编写 下篇文章&#xff1a;C11&#xff1a;新的类功能、模板的可…

Pandas取代Excel?

有人在知乎上提问&#xff1a;为什么大公司不用pandas取代excel&#xff1f; 而且列出了几个理由&#xff1a;Pandas功能比Excel强大&#xff0c;运行速度更快&#xff0c;Excel除了简单和可视化界面外&#xff0c;没有其他更多的优势。 有个可怕的现实是&#xff0c;对比Exce…

Vue 3 中将 ref 创建的响应式对象数据转换为普通(非响应式)的数据

Vue 3 中使用 ref 创建的响应式对象数据转换为普通&#xff08;非响应式&#xff09;的数据&#xff0c;有以下几种方法&#xff1a; 1. 访问 .value 属性: 这是最直接、最常见的方法。 由于 ref 对象的值存储在其 .value 属性中&#xff0c;直接访问该属性即可获得普通数据。…

四月下旬系列

CUHKSZ 校赛 期中考试 DAY -1。 省流&#xff1a;前 1h 切 6 题&#xff0c;后 3h 过 1 题&#xff0c;读错一个本来很【】的题&#xff0c;被大模拟构造创【】了。 本地除了 VSCode 没有 Extensions&#xff0c;别的和省选差不多。使用 DEVC。 前 6 题难度 < 绿&#x…

下采样(Downsampling)

目录 1. 下采样的定义与作用​​ ​​2. 常见下采样方法​​ ​​(1) 池化&#xff08;Pooling&#xff09;​​ ​​(2) 跨步卷积&#xff08;Strided Convolution&#xff09;​​ ​​(3) 空间金字塔池化&#xff08;SPP&#xff09;​​ ​​3. PyTorch 实现示例​​ …

lottie深入玩法

A、json文件和图片资源分开 delete 是json资源名字 /res/lottie/delete_anim_images是图片资源文件夹路径 JSON 中引用的图片名&#xff0c;必须与实际图片文件名一致 B、json文件和图片资源分开&#xff0c;并且图片加载不固定 比如我有7张图片&#xff0c;分别命名1~7&…