diff --git a/typing.css b/typing.css index a1307ea..17debf2 100644 --- a/typing.css +++ b/typing.css @@ -170,6 +170,7 @@ gap: 0.35rem; } .kb-key { + flex: 0 0 auto; min-width: 34px; height: 40px; padding: 0 0.4rem; @@ -179,8 +180,14 @@ color: var(--text); font-size: 0.9rem; font-family: var(--font-mono); - cursor: pointer; + cursor: default; + user-select: none; + display: inline-flex; + align-items: center; + justify-content: center; } +.kb-key.wide { min-width: 64px; } +.kb-key.altgr { min-width: 64px; } .kb-key.space { flex: 1; max-width: 220px; } .kb-key.hint { border-color: var(--accent); @@ -188,6 +195,13 @@ color: #fff; font-weight: 700; } +#special-hint { + min-height: 1.6rem; + margin-top: 0.75rem; + font-size: 0.85rem; + color: var(--text-muted); + line-height: 1.5; +} .finish-box { text-align: center; padding: 2rem 0; @@ -205,10 +219,13 @@ } @media (max-width: 640px) { .kb-key { - min-width: 28px; - height: 38px; - font-size: 0.8rem; - padding: 0 0.25rem; + min-width: 20px; + height: 34px; + font-size: 0.65rem; + padding: 0 0.1rem; + } + .kb-key.wide, .kb-key.altgr { + min-width: 44px; } .kb-row { gap: 0.25rem; } } diff --git a/typing.html b/typing.html index 0d6e2ca..cc3909c 100644 --- a/typing.html +++ b/typing.html @@ -53,6 +53,7 @@
+ diff --git a/typing.js b/typing.js index 77fe0b9..fe16ed0 100644 --- a/typing.js +++ b/typing.js @@ -5,13 +5,62 @@ 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','ñ'], - ['z','x','c','v','b','n','m',',','.',';'], - ['á','é','í','ó','ú','ü','¿','¡',':','?','!',' '] + ['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'] ]; +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', + '¿': 'Windows:AltGr + ?;macOS:Option + Shift + ?;Linux:Compose ? ?', + '¡': 'Windows:AltGr + 1;macOS:Option + 1;Linux:Compose ! !', + '?': 'Shift + /', + '!': 'Shift + 1', + ':': 'Shift + ;' +}; + +function standardKeyForChar(ch) { + if (ch === ' ') return 'Space'; + var lower = ch.toLowerCase(); + if (/[a-z0-9]/.test(lower)) return lower; + var map = { + 'á':'a','é':'e','í':'i','ó':'o','ú':'u','ü':'u','ñ':'n', + '?':'/','¿':'/','!':'1','¡':'1', + ',':',','.':'.',';':';',':':';','-':'-','=':'=', + '[':'[',']':']','\\':'\\',"'":"'",'\"':"'" + }; + return map[ch] || ''; +} + +function renderSpecialHint(ch) { + var el = document.getElementById('special-hint'); + if (!ch) { + el.textContent = ''; + return; + } + if (SPECIAL_HINTS[ch]) { + el.textContent = '输入提示:' + SPECIAL_HINTS[ch]; + return; + } + if (ch === ' ') { + el.textContent = '输入提示:按空格键'; + return; + } + if (ch !== ch.toLowerCase() && ch === ch.toUpperCase() && /[a-z]/i.test(ch)) { + el.textContent = '输入提示:先按 Shift,再按 ' + ch.toLowerCase(); + return; + } + el.textContent = '输入提示:直接按标准键盘上的 ' + (standardKeyForChar(ch) || ch) + ' 键'; +} + function escTyping(s) { var div = document.createElement('div'); div.textContent = s == null ? '' : String(s); @@ -95,9 +144,10 @@ function renderPractice() { function renderNextKey(target) { var next = target[typed.length]; + var label = next === ' ' ? '空格' : next; document.getElementById('next-key').innerHTML = typed.length >= target.length ? '已完成' - : '下一键:' + escTyping(next) + ''; + : '下一键:' + escTyping(label) + ''; } function renderTypingAccuracy() { @@ -109,18 +159,25 @@ 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 container = document.getElementById('keyboard'); container.innerHTML = KEY_ROWS.map(function(row) { return '