一、项目简介
vkeyboardhand 是一个基于 SVG 键盘图 + SVG 手势图 + JavaScript 事件驱动联动 实现的交互式虚拟键盘及指法显示教学系统。
当用户按下真实键盘上的按键(或点击虚拟按键)时,对应的键位会高亮,手部手势图会同步切换,同时底部的"指法提示条"会实时显示"哪个手指按哪个键"------这种三合一的联动反馈,让它成为打字教学中极其直观的工具。 最值得一提的是:纯 HTML + JS 实现,零依赖,可无缝嵌入 Vue、React、Angular 等任何前端框架。 
vkeyboardhand:一个零依赖的交互式虚拟键盘指法教学组件
项目地址:github.com/ayuday/vkey...
在线演示:vk.markdownlang.com
二、核心功能
- 🎹 键盘-手势联动:按下按键时,对应键位高亮 + 手势图同步切换 + 指法提示条实时更新
- ⌨️ KeyboardEvent 驱动:监听 keydown / keyup 事件,支持 Shift / Alt 等组合键手势
- 🖱️ 点击模拟:支持鼠标点击虚拟按键进行演示(可开关)
- 🎨 多主题切换:内置 colorful(彩虹)、bone、dark、robot、kingfish、milk 六种主题
- 🌈 彩虹配色方案:按键按手指分区着色,左冷右暖形成彩虹渐变
- 🧩 框架无关:仅操作 DOM,不依赖任何框架
- ⚙️ 完整 API:提供 press / release / reset / setTheme / setClickEnabled / getState / destroy 等方法及事件回调
- 🗂 可定制映射:三层 key → finger → SVG id 映射表,支持通过配置覆盖
三、应用场景
- 打字教学平台:嵌入在线打字练习网站,帮助初学者学习正确的指法。
- 教育类应用:在 K12 或计算机基础课程中作为教学辅助工具。
- 技术博客/文档:在介绍键盘快捷键的文章中嵌入交互演示。
- 辅助工具:为有特殊需求的用户提供可视化按键反馈。
- 产品展示:在键盘硬件产品页面中展示按键映射和指法建议。
- 游戏化学习:结合打字游戏,实时反馈用户的手指位置是否正确。
四、项目特点
- 零依赖,极致轻量
- 纯 JavaScript + SVG 实现,不依赖任何第三方库,打包体积极小,加载速度快。
- 框架无关 组件只操作 DOM,可在任何环境中使用: ✅ 原生 HTML ✅ Vue 2 / Vue 3 ✅ React ✅ Angular ✅ 其他任何框架
三种引入方式
本地引入 CDN(jsDelivr / unpkg) npm + ESM
丰富的配置项 支持主题切换、按键映射自定义、手指映射自定义、点击开关、双手显示模式等十余项配置。
SVG 矢量图形 键盘和手势均采用 SVG 绘制,清晰度高、缩放无损、文件体积小。
五、技术栈
| 技术 | 用途 |
|---|---|
| SVG(内联注入) | 键盘图 + 手指手势图 |
| JavaScript DOM 操作 | 控制 SVG 元素的可见性和样式 |
| KeyboardEvent API | 监听用户按键 |
| CSS Transition / Animation | 按键动画、高亮过渡 |
| 数据映射表 | key → finger → SVG id 三层映射 |
| fetch / inline | 加载 SVG 文件 |
| Node.js 构建脚本 | 生成 UMD + ESM + CSS |
| GitHub Actions | CI/CD 自动发布 |
六、使用方法
方式一:纯 HTML + JS(本地引入)
xml
<!-- 引入样式 -->
<link rel="stylesheet" href="dist/vkeyboardhand.css">
<!-- 引入脚本(UMD,挂载为 window.VKeyboardHand) -->
<script src="dist/vkeyboardhand.umd.js"></script>
<div id="demo"></div>
<script>
var kb = VKeyboardHand.create('#demo', {
keyboard: './svg/keyboard.svg',
hand: './svg/hand.svg'
});
</script>
方式二:CDN 引入
xml
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vkeyboardhand@latest/dist/vkeyboardhand.css">
<script src="https://cdn.jsdelivr.net/npm/vkeyboardhand@latest/dist/vkeyboardhand.umd.js"></script>
<div id="demo"></div>
<script>
var kb = VKeyboardHand.create('#demo', {
keyboard: 'https://cdn.jsdelivr.net/npm/vkeyboardhand@latest/svg/keyboard.svg',
hand: 'https://cdn.jsdelivr.net/npm/vkeyboardhand@latest/svg/hand.svg'
});
</script>
方式三:npm 安装(适用于框架项目)
npm install vkeyboardhand
Vue 3 示例
xml
<template>
<div ref="host"></div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import VKeyboardHand from 'vkeyboardhand';
import 'vkeyboardhand/vkeyboardhand.css';
const host = ref(null);
let kb = null;
onMounted(() => {
kb = VKeyboardHand.create(host.value, {
keyboard: '/assets/svg/keyboard.svg',
hand: '/assets/svg/hand.svg'
});
});
onBeforeUnmount(() => kb && kb.destroy());
</script>
React 示例
javascript
import { useEffect, useRef } from 'react';
import VKeyboardHand from 'vkeyboardhand';
import 'vkeyboardhand/vkeyboardhand.css';
export default function FingerTeaching() {
const host = useRef(null);
useEffect(() => {
const kb = VKeyboardHand.create(host.current, {
keyboard: '/assets/svg/keyboard.svg',
hand: '/assets/svg/hand.svg'
});
return () => kb.destroy();
}, []);
return <div ref={host} />;
}
Angular 示例
typescript
import { Component, ElementRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
import VKeyboardHand from 'vkeyboardhand';
@Component({
selector: 'app-finger-teaching',
template: <div #host></div>
})
export class FingerTeachingComponent implements AfterViewInit, OnDestroy {
@ViewChild('host', { static: true }) host!: ElementRef<HTMLDivElement>;
private kb: any = null;
ngAfterViewInit(): void {
this.kb = VKeyboardHand.create(this.host.nativeElement, {
keyboard: 'assets/svg/keyboard.svg',
hand: 'assets/svg/hand.svg'
});
}
ngOnDestroy(): void { this.kb?.destroy(); }
}
七、API 速览
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
keyboard |
string / SVGElement | './svg/keyboard.svg' |
键盘 SVG 来源 |
hand |
string / SVGElement | './svg/hand.svg' |
手势 SVG 来源 |
theme |
string | 'colorful' |
主题名称 |
listenKeyboard |
boolean | true |
是否监听真实键盘 |
enableClick |
boolean | true |
是否允许点击演示 |
showFingerLabel |
boolean | true |
是否显示指法提示条 |
showHandBoth |
boolean | true |
按键时是否保持双手自然状态可见 |
holdDelay |
number | 80 |
手势过渡延迟(ms) |
keyMap |
object | 内置 | 自定义按键映射 |
fingerMap |
object | 内置 | 自定义手指映射 |
实例方法
| 方法 | 说明 |
|---|---|
press(key) |
模拟按下指定键 |
release(key) |
释放指定键 |
reset() |
重置所有高亮和手势 |
setTheme(theme) |
切换主题 |
setClickEnabled(bool) |
启用/禁用点击 |
getState() |
获取当前按下的键列表 |
getFinger(key) |
获取某键对应的手指信息 |
destroy() |
销毁组件,释放资源 |
八、手指分区与配色
默认 colorful 主题下,按键按手指分区着色:
| 手指 | ID | 默认颜色 |
|---|---|---|
| 左手小指 | lp |
🟠 #ff9f43 |
| 左手无名指 | lr |
🟣 #f368e0 |
| 左手中指 | lm |
🔵 #17c0eb |
| 左手食指 | li |
🟢 #1dd1a1 |
| 右手食指 | ri |
🔵 #0abde3 |
| 右手中指 | rm |
🟣 #a29bfe |
| 右手无名指 | rr |
🩷 #fd79a8 |
| 右手小指 | rp |
🟡 #fdcb6e |
| 拇指 | th |
🟣 #6c5ce7 |
支持通过 CSS 变量自定义颜色:
css
.vk-hand {
--vk-finger-lp: #ff6348;
--vk-accent: #38bdf8;
}
九、总结
vkeyboardhand 是一个设计精巧、开箱即用的虚拟键盘指法教学组件。它的核心优势在于:
✅ 零依赖:不引入任何第三方库,轻量无负担 ✅ 框架无关:一套代码适配所有前端框架 ✅ 视觉直观:SVG 矢量图 + 彩虹配色,教学体验极佳 ✅ 高度可定制:主题、映射、颜色均可覆盖 ✅ MIT 开源:可自由用于商业项目
如果你正在开发打字教学、键盘演示或任何需要可视化按键交互的项目,vkeyboardhand 是一个值得尝试的优秀选择。
⭐ 觉得有用?去 GitHub 给个项目一个 Star 吧! → github.com/ayuday/vkeyboardhand