diff --git a/typing.css b/typing.css index 17debf2..066e21a 100644 --- a/typing.css +++ b/typing.css @@ -185,7 +185,16 @@ display: inline-flex; align-items: center; justify-content: center; + flex-direction: column; + line-height: 1.05; } +.kb-key .kb-main { font-size: 1em; } +.kb-key .kb-sub { + font-size: 0.62em; + opacity: 0.6; + margin-top: 1px; +} +.kb-key.hint .kb-sub { opacity: 0.9; } .kb-key.wide { min-width: 64px; } .kb-key.altgr { min-width: 64px; } .kb-key.space { flex: 1; max-width: 220px; } @@ -202,6 +211,26 @@ color: var(--text-muted); line-height: 1.5; } +.keyboard-guide { + margin-top: 1rem; + padding: 0.9rem 1rem; + background: var(--highlight); + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 0.86rem; + line-height: 1.7; + color: var(--text-muted); +} +.keyboard-guide h2 { + margin: 0 0 0.5rem; + font-size: 0.95rem; + color: var(--text); +} +.keyboard-guide ol { + margin: 0; + padding-left: 1.25rem; +} +.keyboard-guide li { margin-bottom: 0.25rem; } .finish-box { text-align: center; padding: 2rem 0; @@ -219,13 +248,19 @@ } @media (max-width: 640px) { .kb-key { - min-width: 20px; + flex: 1 1 0; + min-width: 0; height: 34px; - font-size: 0.65rem; - padding: 0 0.1rem; + font-size: 0.62rem; + padding: 0 0.05rem; } .kb-key.wide, .kb-key.altgr { - min-width: 44px; + min-width: 40px; } + .kb-key.space { min-width: 56px; max-width: 140px; } .kb-row { gap: 0.25rem; } + .keyboard-guide { + font-size: 0.8rem; + padding: 0.75rem; + } } diff --git a/typing.html b/typing.html index cc3909c..241da1b 100644 --- a/typing.html +++ b/typing.html @@ -54,6 +54,25 @@
+
+

西语键盘按键说明

+
    +
  1. 字母 ñ:点击“;”键,即字母 L 右边第一个键。
  2. +
  3. 字母 á é í ó ú:引号键 + a e i o u,引号键是字母 L 右边第二个键。
  4. +
  5. 倒问号 ¿:Shift + 加号键。
  6. +
  7. 问号 ?:Shift + 减号键。
  8. +
  9. 倒感叹号 ¡:直接按加号键。
  10. +
  11. 感叹号 !:Shift + 数字 1。
  12. +
  13. 快速切换键盘:Shift + Alt。
  14. +
  15. 横线 ——:原键盘上的问号键,单击即可。
  16. +
  17. 括号 ():Shift + 数字 8、9。
  18. +
  19. 引号 “”:Shift + 数字 2。
  20. +
  21. 斜线 /:Shift + 数字 7。
  22. +
  23. 分号 ;:Shift + 逗号键。
  24. +
  25. 冒号 ::Shift + 句号键。
  26. +
  27. ü:Shift + 引号键,松开后输入 u。
  28. +
+
diff --git a/typing.js b/typing.js index 54a3303..1ff4903 100644 --- a/typing.js +++ b/typing.js @@ -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 '
' + row.map(function(key) { - var isHint = key.toLowerCase() === String(base || '').toLowerCase() || - (key === 'Shift' && (shiftNeeded || shiftPunctuation)) || - (key === 'AltGr' && specialNeeded); + return '
' + 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 '
' + escTyping(key) + '
'; + var face = sub + ? '' + escTyping(key) + '' + escTyping(sub) + '' + : escTyping(key); + return '
' + face + '
'; }).join('') + '
'; }).join(''); renderSpecialHint(next);