fix: 打字键盘改为西语键位并修复按键高亮

This commit is contained in:
guoqingshan
2026-08-02 22:09:05 +08:00
parent 7391007b74
commit ea33642f79
3 changed files with 172 additions and 38 deletions
+114 -34
View File
@@ -5,39 +5,105 @@ var typingStats = { correct: 0, errors: 0 };
var typed = '';
var KEY_ROWS = [
['1','2','3','4','5','6','7','8','9','0','-','='],
['q','w','e','r','t','y','u','i','o','p','[',']','\\'],
['a','s','d','f','g','h','j','k','l',';','\''],
['Shift','z','x','c','v','b','n','m',',','.','/','Shift'],
['Ctrl','Alt','Space','AltGr','Ctrl']
[
{ key: 'º', sub: '`' },
{ key: '1' }, { key: '2' }, { key: '3' }, { key: '4' }, { key: '5' },
{ key: '6' }, { key: '7' }, { key: '8' }, { key: '9' }, { key: '0' },
{ key: "'", sub: '-' }, { key: '¡', sub: '=' }
],
[
{ key: 'q' }, { key: 'w' }, { key: 'e' }, { key: 'r' }, { key: 't' },
{ key: 'y' }, { key: 'u' }, { key: 'i' }, { key: 'o' }, { key: 'p' },
{ key: '`', sub: '[' }, { key: '+', sub: ']' }, { key: 'ç', sub: '\\' }
],
[
{ key: 'a' }, { key: 's' }, { key: 'd' }, { key: 'f' }, { key: 'g' },
{ key: 'h' }, { key: 'j' }, { key: 'k' }, { key: 'l' },
{ key: 'ñ', sub: ';' }, { key: '´', sub: "'" }
],
[
{ key: 'Shift' }, { key: '<' }, { key: 'z' }, { key: 'x' }, { key: 'c' },
{ key: 'v' }, { key: 'b' }, { key: 'n' }, { key: 'm' }, { key: ',' },
{ key: '.' }, { key: '-', sub: '/' }, { key: 'Shift' }
],
[
{ key: 'Ctrl' }, { key: 'Win' }, { key: 'Alt' }, { key: 'Space' },
{ key: 'AltGr' }, { key: 'Ctrl' }
]
];
var SPECIAL_HINTS = {
'á': 'Windows 美式国际:先按 \' 再按 a;macOS:Option + e 再按 a;手机长按 a',
'é': 'Windows 美式国际:先按 \' 再按 e;macOS:Option + e 再按 e;手机长按 e',
'í': 'Windows 美式国际:先按 \' 再按 i;macOS:Option + e 再按 i;手机长按 i',
'ó': 'Windows 美式国际:先按 \' 再按 o;macOS:Option + e 再按 o;手机长按 o',
'ú': 'Windows 美式国际:先按 \' 再按 u;macOS:Option + e 再按 u;手机长按 u',
'ü': 'Windows 美式国际:先按 " 再按 u;macOS:Option + u 再按 u;手机长按 u',
'ñ': 'Windows:AltGr + n 或先按 ~ 再按 n;macOS:Option + n 再按 n;手机长按 n',
'¿': '西班牙语键盘:Shift + 加号键;美式国际键盘:AltGr + ?;macOS:Option + Shift + ?;数字键盘:Alt + 0191',
'¡': '西班牙语键盘:直接按加号键;美式国际键盘:AltGr + 1;macOS:Option + 1;数字键盘:Alt + 0161',
'?': '西班牙语键盘:Shift + 减号键;美式国际键盘:Shift + /',
'á': '先按 L 右边的 ´ 键,再按 a',
'é': '先按 L 右边的 ´ 键,再按 e',
'í': '先按 L 右边的 ´ 键,再按 i',
'ó': '先按 L 右边的 ´ 键,再按 o',
'ú': '先按 L 右边的 ´ 键,再按 u',
'Á': '先按 L 右边的 ´ 键,再按 Shift + A',
'É': '先按 L 右边的 ´ 键,再按 Shift + E',
'Í': '先按 L 右边的 ´ 键,再按 Shift + I',
'Ó': '先按 L 右边的 ´ 键,再按 Shift + O',
'Ú': '先按 L 右边的 ´ 键,再按 Shift + U',
'ü': 'Shift + L 右边的 ´ 键,松开后按 u',
'Ü': 'Shift + L 右边的 ´ 键,松开后按 Shift + U',
'ñ': '直接按 L 右边的 ñ 键',
'Ñ': 'Shift + L 右边的 ñ 键',
'¿': 'Shift + ¡ 键(标准键盘上是 Shift + 加号键)',
'¡': '直接按 ¡ 键(标准键盘上是加号键)',
'?': 'Shift + \' 键(标准键盘上是 Shift + 减号键)',
'!': 'Shift + 数字 1',
':': 'Shift + ;'
':': 'Shift + 句号键',
';': 'Shift + 逗号键'
};
function standardKeyForChar(ch) {
if (ch === ' ') return 'Space';
function keyPressForChar(ch) {
if (!ch) return null;
if (ch === ' ') return { keys: ['Space'], shift: false };
var lower = ch.toLowerCase();
if (/[a-z0-9]/.test(lower)) return lower;
if (/[a-z0-9]/.test(lower)) {
return { keys: [lower], shift: ch !== lower };
}
var map = {
'á':'a','é':'e','í':'i','ó':'o','ú':'u','ü':'u','ñ':'n',
'?':'/','¿':'/','!':'1','¡':'1',
',':',','.':'.',';':';',':':';','-':'-','=':'=',
'[':'[',']':']','\\':'\\',"'":"'",'\"':"'"
'á': { keys: ['´'], shift: false },
'é': { keys: ['´'], shift: false },
'í': { keys: ['´'], shift: false },
'ó': { keys: ['´'], shift: false },
'ú': { keys: ['´'], shift: false },
'Á': { keys: ['´'], shift: false },
'É': { keys: ['´'], shift: false },
'Í': { keys: ['´'], shift: false },
'Ó': { keys: ['´'], shift: false },
'Ú': { keys: ['´'], shift: false },
'ü': { keys: ['´'], shift: true },
'Ü': { keys: ['´'], shift: true },
'ñ': { keys: ['ñ'], shift: false },
'Ñ': { keys: ['ñ'], shift: true },
'¿': { keys: ['¡'], shift: true },
'¡': { keys: ['¡'], shift: false },
'?': { keys: ["'"], shift: true },
'!': { keys: ['1'], shift: true },
':': { keys: ['.'], shift: true },
';': { keys: [','], shift: true },
'/': { keys: ['7'], shift: true },
'"': { keys: ['2'], shift: true },
'(': { keys: ['8'], shift: true },
')': { keys: ['9'], shift: true },
'_': { keys: ['-'], shift: true },
'-': { keys: ['-'], shift: false },
"'": { keys: ["'"], shift: false },
',': { keys: [','], shift: false },
'.': { keys: ['.'], shift: false },
'<': { keys: ['<'], shift: false },
'>': { keys: ['<'], shift: true },
'`': { keys: ['`'], shift: false },
'^': { keys: ['`'], shift: true },
'+': { keys: ['+'], shift: false },
'*': { keys: ['+'], shift: true },
'º': { keys: ['º'], shift: false },
'ª': { keys: ['º'], shift: true },
'ç': { keys: ['ç'], shift: false },
'Ç': { keys: ['ç'], shift: true }
};
return map[ch] || '';
return map[ch] || null;
}
function renderSpecialHint(ch) {
@@ -54,11 +120,16 @@ function renderSpecialHint(ch) {
el.textContent = '输入提示:按空格键';
return;
}
var press = keyPressForChar(ch);
if (press && press.shift) {
el.textContent = '输入提示:先按 Shift,再按 ' + press.keys.join(' + ') + ' 键';
return;
}
if (ch !== ch.toLowerCase() && ch === ch.toUpperCase() && /[a-z]/i.test(ch)) {
el.textContent = '输入提示:先按 Shift,再按 ' + ch.toLowerCase();
return;
}
el.textContent = '输入提示:直接按标准键盘上的 ' + (standardKeyForChar(ch) || ch) + ' 键';
el.textContent = '输入提示:直接按 ' + (press ? press.keys.join(' + ') : ch) + ' 键';
}
function escTyping(s) {
@@ -159,22 +230,31 @@ function renderTypingAccuracy() {
function renderKeyboard(target) {
var next = target[typed.length] || '';
var base = standardKeyForChar(next);
var shiftNeeded = next && next !== next.toLowerCase() && next === next.toUpperCase() && /[a-z]/i.test(next);
var specialNeeded = next && /[áéíóúüñ¿¡]/.test(next);
var shiftPunctuation = next === '?' || next === '!' || next === ':';
var press = keyPressForChar(next);
var highlightKeys = {};
var highlightShift = false;
if (press) {
press.keys.forEach(function(key) {
highlightKeys[key.toLowerCase()] = true;
});
highlightShift = press.shift;
}
var container = document.getElementById('keyboard');
container.innerHTML = KEY_ROWS.map(function(row) {
return '<div class="kb-row">' + row.map(function(key) {
var isHint = key.toLowerCase() === String(base || '').toLowerCase() ||
(key === 'Shift' && (shiftNeeded || shiftPunctuation)) ||
(key === 'AltGr' && specialNeeded);
return '<div class="kb-row">' + row.map(function(item) {
var key = item.key;
var sub = item.sub || '';
var isHint = highlightKeys[key.toLowerCase()] ||
(key === 'Shift' && highlightShift);
var cls = ['kb-key'];
if (isHint) cls.push('hint');
if (key === 'Shift' || key === 'Ctrl' || key === 'Alt') cls.push('wide');
if (key === 'AltGr') cls.push('altgr');
if (key === 'Space') cls.push('space');
return '<div class="' + cls.join(' ') + '">' + escTyping(key) + '</div>';
var face = sub
? '<span class="kb-main">' + escTyping(key) + '</span><span class="kb-sub">' + escTyping(sub) + '</span>'
: escTyping(key);
return '<div class="' + cls.join(' ') + '">' + face + '</div>';
}).join('') + '</div>';
}).join('');
renderSpecialHint(next);