chinese-keyboard.js
Version:
中文键盘:支持VUE2、VUE3、REACT、以及原生JS
456 lines (395 loc) • 10.8 kB
HTML
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no"
/>
<title>中文虚拟键盘演示</title>
<link rel="stylesheet" href="src/keyboard-dark.css" />
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
min-height: 100vh;
box-sizing: border-box;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 32px;
font-size: 32px;
}
.demo-section {
margin-bottom: 32px;
}
.demo-section h2 {
color: #007bff;
font-size: 26px;
margin-bottom: 16px;
border-bottom: 2px solid #e9ecef;
padding-bottom: 8px;
}
.input-group {
margin-bottom: 20px;
}
.input-group label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #495057;
}
.demo-input {
width: 100%;
padding: 12px 16px;
border: 2px solid #dee2e6;
border-radius: 8px;
font-size: 20px;
transition: border-color 0.2s ease;
box-sizing: border-box;
}
.demo-input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.demo-textarea {
width: 100%;
min-height: 120px;
padding: 12px 16px;
border: 2px solid #dee2e6;
border-radius: 8px;
font-size: 20px;
font-family: inherit;
resize: vertical;
transition: border-color 0.2s ease;
box-sizing: border-box;
}
.demo-textarea:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.controls {
display: flex;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 6px;
font-size: 20px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
background: #007bff;
color: white;
}
.btn:hover {
background: #0056b3;
transform: translateY(-1px);
}
.btn:active {
transform: translateY(0);
}
.btn-secondary {
background: #6c757d;
}
.btn-secondary:hover {
background: #5a6268;
}
.btn-success {
background: #28a745;
}
.btn-success:hover {
background: #1e7e34;
}
.status {
background: #e3f2fd;
border: 1px solid #bbdefb;
border-radius: 6px;
padding: 12px;
margin-bottom: 20px;
}
.status-item {
margin-bottom: 8px;
}
.status-item:last-child {
margin-bottom: 0;
}
.status-label {
font-weight: 500;
color: #1976d2;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 32px;
}
.feature-card {
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
text-align: center;
}
.feature-icon {
font-size: 40px;
margin-bottom: 12px;
}
.feature-title {
font-weight: 600;
margin-bottom: 8px;
color: #333;
}
.feature-desc {
color: #6c757d;
font-size: 20px;
}
.theme-selector {
display: flex;
gap: 20px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.theme-option {
display: flex;
align-items: center;
cursor: pointer;
padding: 12px 16px;
border: 2px solid #dee2e6;
border-radius: 8px;
background: white;
transition: all 0.2s ease;
min-width: 140px;
}
.theme-option:hover {
border-color: #007bff;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.15);
}
.theme-option input[type="radio"] {
margin-right: 8px;
transform: scale(1.2);
accent-color: #007bff;
}
.theme-label {
font-size: 18px;
font-weight: 500;
color: #495057;
}
.theme-option input[type="radio"]:checked + .theme-label {
color: #007bff;
font-weight: 600;
}
.theme-option:has(input[type="radio"]:checked) {
border-color: #007bff;
background: #f8f9ff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
.theme-status {
background: #e3f2fd;
border: 1px solid #bbdefb;
border-radius: 6px;
padding: 12px;
margin-top: 16px;
text-align: center;
font-weight: 500;
color: #1976d2;
font-size: 18px;
}
.footer {
text-align: center;
margin-top: 40px;
padding-top: 20px;
border-top: 1px solid #e9ecef;
color: #6c757d;
font-size: 14px;
}
/* 移动端优化 */
@media (max-width: 768px) {
body {
padding: 10px;
}
.container {
padding: 16px;
}
h1 {
font-size: 24px;
}
.controls {
gap: 8px;
}
.btn {
padding: 8px 16px;
font-size: 20px;
}
.features {
grid-template-columns: 1fr;
gap: 16px;
}
}
</style>
</head>
<body>
<div class="container">
<h1>🎹 中文虚拟键盘演示</h1>
<!-- 输入测试 -->
<div class="demo-section">
<h2>✏️ 输入测试</h2>
<div class="input-group">
<label for="demo-input">单行输入框 (点击激活键盘):</label>
<input
type="text"
id="demo-input"
class="demo-input"
placeholder="点击这里开始输入..."
/>
</div>
<div class="input-group">
<label for="demo-textarea">多行文本框:</label>
<textarea
id="demo-textarea"
class="demo-textarea"
placeholder="在这里输入更多文字..."
></textarea>
</div>
</div>
<!-- 主题切换 -->
<div class="demo-section">
<h2>🎨 主题切换</h2>
<div class="theme-selector">
<label class="theme-option">
<input type="radio" name="theme" value="dark" checked />
<span class="theme-label">🌙 深色模式</span>
</label>
<label class="theme-option">
<input type="radio" name="theme" value="light" />
<span class="theme-label">☀️ 浅色模式</span>
</label>
<label class="theme-option">
<input type="radio" name="theme" value="china-red" />
<span class="theme-label">🇨🇳 中国红模式</span>
</label>
</div>
<div class="theme-status">当前主题: 🌙 深色模式</div>
</div>
<div class="footer">
<p>© 2025 中文虚拟键盘 - 支持 Vue、React、Uniapp 等多种框架</p>
</div>
</div>
<!-- 引入字库和键盘脚本 -->
<script src="src/keyboard.js"></script>
<script>
// 全局变量
let keyboard = null;
let currentTheme = 'dark';
// 主题切换函数
function switchTheme(theme) {
if (currentTheme === theme) return;
currentTheme = theme;
// 移除旧的CSS链接
const oldLink = document.querySelector('link[href*="keyboard-"]');
if (oldLink) {
oldLink.remove();
}
// 添加新的CSS链接
const newLink = document.createElement('link');
newLink.rel = 'stylesheet';
newLink.href = `src/keyboard-${theme}.css`;
document.head.appendChild(newLink);
// 重新初始化键盘
if (keyboard) {
keyboard.destroy();
}
initKeyboard();
// 更新状态显示
updateThemeStatus();
}
// 更新主题状态显示
function updateThemeStatus() {
const statusDiv = document.querySelector('.theme-status');
if (statusDiv) {
statusDiv.textContent = `当前主题: ${getThemeDisplayName(currentTheme)}`;
}
}
// 获取主题显示名称
function getThemeDisplayName(theme) {
const themeNames = {
'dark': '🌙 深色模式',
'light': '☀️ 浅色模式',
'china-red': '🇨🇳 中国红模式'
};
return themeNames[theme] || theme;
}
// 初始化键盘
function initKeyboard() {
keyboard = new ChineseKeyboard();
keyboard.addCustomDictionary("hd", ["好的", "互动", "后端", "很多"]);
keyboard.addCustomDictionary("zt", [
"载体",
"状态",
"昨天",
"主题",
"字体",
"暂停",
]);
keyboard.addCustomDictionary("gly", [
"管理员",
"root",
"橄榄油",
"鼓浪屿",
"过来呀",
]);
keyboard.addCustomDictionary("cnm", [
"不文明",
"很不文明",
"请不要说脏话",
"做个文明人",
"草拟吗",
]);
keyboard.addCustomDictionary("zz", [
"转转",
"制作"
]);
keyboard.addCustomDictionary("jntm", [
"姬霓太美",
"鸡你太美",
"加内特吗"
]);
keyboard.addCustomDictionary("xz", [
"肖战",
"现在",
"新增",
]);
}
// 页面加载完成后初始化
document.addEventListener("DOMContentLoaded", () => {
initKeyboard();
// 添加主题切换事件监听器
const themeRadios = document.querySelectorAll('input[name="theme"]');
themeRadios.forEach(radio => {
radio.addEventListener('change', (e) => {
if (e.target.checked) {
switchTheme(e.target.value);
}
});
});
});
</script>
</body>
</html>