近,知乎在桌面端網頁上陸續增加了一些快捷鍵:
在非輸入狀態下按 ?(Shift+/)就可以查看快捷鍵列表
在開發快捷鍵的過程中,有一些值得分享的經驗。
實現快捷鍵不困難,因為監聽鍵盤事件很簡單。大部分時候,我們只需要在希望響應事件的最外層元素上注冊事件就行,而響應事件的回調(比如關閉模態框)也都可以在這個最外層組件內實現。
知乎首頁的組件結構
但是這次的情況要更加復雜。以在首頁按 V 贊同答案為例:列表內的時間線條目(FeedItem)包括了回答(AnswerItem)在內各種類型的內容,而在回答里的贊同按鈕(VoteButton)才是適合響應快捷鍵事件的地方。在最外側的 FeedItem 上容易注冊事件卻無法響應事件,在最內側的 VoteButton 中可以響應事件卻不能簡單地注冊事件。
如何在 React 的組件關系中優雅地實現子組件(贊同、收藏按鈕等)注冊快捷鍵和回調函數、同時直到父組件(整個回答甚至 Feed 條目)的范圍內都可以響應快捷鍵是比較有趣的。
一種簡單的想法是:放棄在子組件中注冊快捷鍵,全部在父組件中注冊快捷鍵,在回調的時候調用子組件的實例方法。這會造成以下這些問題:
現在知乎使用的方案是:基于 React context 來為所有子組件共享一個「快捷鍵實例」,在這個「作用域」下的所有子組件聲明快捷鍵時,都會注冊到這個實例上面。
參考下方的偽代碼:
function FeedItem() {
const feedItemElement=useRef(null)
return (
<ShortcutContext value={feedItemElement}>
<div className="FeedItem" ref={feedItemElement}>
<AnswerItem />
</div>
</ShortcutContext>
)
}
在 FeedItem 中,以自身的 HTML element 來初始化一個新的快捷鍵實例并設置在 context 中,實際的 keydown 等鍵盤事件是注冊在這個 element 上。所以子組件都可以通過 context 在這個實例上注冊新的快捷鍵。
function VoteButton() {
const handleVote=()=> console.log('voting')
// 在 useShortcut 中查找當前 context 中存在的快捷鍵實例,并注冊在實例上
useShortcut('v', handleVote)
return <button onClick={handleVote}>贊同</button>
}
在 VoteButton 中,就可以像響應點擊事件一樣注冊并響應快捷鍵事件,看起來和寫起來都非常清爽。
使用 J、K 進行 Vim 風格的列表導航是許多網站常見的快捷鍵設計[2]。下面是一些如果從零開始實現時,可能會遇到的細節問題:
當使用快捷鍵進行瀏覽時,「知道光標在哪里」很重要。屏幕閱讀器可以閱讀當前 focus 元素的內容。如果不通過聲音的話、就只能通過視覺樣式來知道當前正在 focus 的元素是什么。
Chrome 為 Input 標簽默認添加的 focus outline
瀏覽器默認會為可 focus 的元素通過 :focus 偽類增加一個 outline 樣式,因為這個樣式不是很好看,再加上可 focus 的元素往往也會單獨設計一些響應點擊的樣式,所以一般產品或設計會要求工程師取消掉該樣式。但是如果簡單取消所有 focus 樣式后,用鼠標當然知道「我在點哪里」,但在使用鍵盤訪問的場合就根本不知道「我在哪里」了。
最優雅的方案是使用 CSSWG 的 :focus-visible 偽類來添加 focus 樣式(同時禁用原先的 :focus 樣式),在 WICG 對該樣式的 polyfill 中有詳細的介紹。簡單來說,就是「只有用鍵盤觸發的 focus 才應該添加 focus 樣式」。
知乎按鈕的 focus 樣式
知乎通過和該 polyfill 類似的思想實現了這一設計:在使用鍵盤操作后,會為 <html> 元素添加 data-focus-visible 屬性。只有在包含該屬性的情況下,各個元素才會添加 focus 樣式。而且知乎還修改了默認的樣式、更為美觀。你可以使用 Tab 鍵 tab 到贊同按鈕上查看這個效果。
在開發這一部分功能的時候,還有一個特殊的設計:使用 ?+C 等快捷鍵進行復制粘貼操作(準確地說,是按鍵中包括 Control 或 Shift 等 Modifier Key)時,不認為是一般的鍵盤操作,也不展現 focus outline,否則 outline 會過于頻繁地時有時無。有意思的是,Twitter 其實也已經做了類似的處理,讓人感到大洋兩岸的工程師都在為用戶體驗而努力…
很多關于快捷鍵的討論都會有視障用戶的參與,因為使用屏幕閱讀器瀏覽網頁、必須使用包括 Tab 鍵在內的各種鍵盤快捷鍵進行光標定位與操作,他們是「最會用鍵盤刷知乎」的人。但是,對視障用戶的支持遠不止添加快捷鍵這么簡單。
@devil纏
在一個答案的評論區[6]提到:
如果只是單個按鍵,(快捷鍵)基本上沒有任何用處。以 V 為例:當用 Tab 到達「贊同」按鈕時,直接(按)空格就可以點贊同。(另外)如果在查看內容區點擊 V,焦點不會跑到「贊同」按鈕上。
合理的快捷鍵有可能用處不大,而不合理的快捷鍵不但不能幫助視障用戶,還會幫倒忙。
@殷曉波
和
@devil纏
都提到「使用 V 贊同之后,希望可以 focus 到贊同按鈕」,如果不真正使用屏幕閱讀器瀏覽網頁,是無法想象這句話的原因的:
快捷鍵贊同后,需要轉移焦點
簡單來說,屏幕閱讀器只有在焦點改變時才會閱讀焦點內的文字,它監控不到「贊同按鈕變深藍」這樣普通人可以輕松理解的設計反饋。如果使用快捷鍵贊同后不改變焦點,連按下鍵盤發生了什么都不知道,也就不會知道「已經贊同了答案」。此時 tab 到贊同按鈕上閱讀到「已贊同」的文字才知道發生了什么就很奇怪。
瀏覽器的點擊行為會自動 focus 在可交互的元素上(例如 <button> 或 <a>),而此時按 Enter 或 Space 等快捷鍵可以「模擬一次點擊」,這套現成的體系很容易被忽略。在實際體驗中,tab 到「閱讀全文」按鈕再按 Space 來展開全文并不比用快捷鍵 O 來展開全文麻煩很多。
除此之外,很多讀屏軟件或者視障用戶也會定義、開發個性化的快捷鍵[6]。這么來看,使用 <button> 等語義化標簽使元素可交互元素也可以被 focus、盡可能使用 <a> 而不是在監聽 onClick 事件時使用 location.href 進行頁面跳轉、配置好 aria 屬性等…對 Accessibility 更有意義。
總的來說,實現快捷鍵和實現其他功能一樣也要注意視障用戶的使用、交互體驗,比如:
快捷鍵只是 Accessibility 的一部分,而可訪問性又是一個更加系統和復雜的工程。知乎做了一些努力[7],但還遠遠不夠。也歡迎對這個領域有更多了解的朋友提出建議。
是的。如果你使用 Vimperator 或者 Vimium 等瀏覽器擴展定制了快捷鍵而不想和知乎的沖突,可以在桌面端網頁的個人偏好設置(https://www.zhihu.com/settings/preference)中關閉快捷鍵[8]。
這是編輯器的新功能,會在開放后再行介紹。
^這些快捷鍵在遷移到新版 Web 頁面時沒有同步遷移,在很長一段時間內都沒有實現。
^包括 Twitter、Facebook、Gmail 與新浪微博等,知乎從這些網站的實現細節中受益良多。
^一個叫 tabbable 的庫中有關于這兩者區別的介紹,這個庫在實現 focus trap 等效果時很有用。 https://github.com/davidtheclark/tabbable
^如何高效地查找離視窗最近、滾動距離最小的元素,這個算法比較有意思,這里不贅述了。
^知乎和 Facebook 與新浪微博一樣,會選中視野內可見的新元素,而 Twitter 會放棄滾動。
^ab根據 @devil纏 在這個答案評論區中的說法,他使用的讀屏環境還會定義包括 K 下跳 10 個鏈接、Shift+K 上跳 10 個鏈接等快捷鍵 https://www.zhihu.com/question/19842222/answer/17152043
^@長天之云 的答案介紹了一些知乎對 a11y 的支持 https://www.zhihu.com/question/20487917/answer/15265930
^只在當前使用的瀏覽器中生效。
作者:孫北吉
出處:https://zhuanlan.zhihu.com/p/59928288
Markdown 其實在 2004 年就有了,不過之前一直很小眾,這幾年隨著相關應用平臺的發展,Markdown以其獨到的優勢迅速火起來了。Markdown編輯器使用一套格式標記語言來對文檔內容進行排版和格式顯示。而Markdown的標記很少,常用的也就十個左右,它是一種非常輕量的標記語言。
Markdown編輯器深受技術人員的喜愛,Markdown可以用來編寫說明文檔,用它寫的文檔很多技術平臺都能通用;Markdown可以用來寫技術博客,可以使說明部分和代碼都非常清晰易讀;Markdown格式轉換方便,還可以輕松地將文本轉換為 html、pdf等。
按照Markdown編輯器的使用環境,可以將它們歸納為三類。
這三類軟件分別面向三類Markdown用戶,大家可以根據自己的需求來選擇使用。
下面是我收集的一些業界比較受歡迎的Markdown編輯器,喜歡用Markdown的朋友可以一起看看,一起探討。
Mou 是一款由國人開發的Markdown 編輯器,支持實時預覽,但是僅支持 蘋果操作系統,可以說是目前最好用的免費 Markdown 編輯器,對漢字兼容性非常好。提供語法高亮、在線預覽、同步滾動、全屏模式,支持自定保存、自動匹配,允許自定義主題等等。支持 CSS,HTML 和 PDF 導出等功能。
Mou是獨立的軟件。
更多介紹及下載:http://25.io/mou/
MarkdownPad被很多人稱贊為windows下最好用的Markdown編輯器之一,不過僅支持windows。它有免費版和收費版(MarkdownPad Pro),一般情況下免費版就夠用了,想用pro版的可以自行網上下載,強大的國人crack無處不在的~ ~。
MarkdownPad支持鍵盤快捷鍵和工具欄操作,即可添加標記也可移除,支持即時HTML預覽、支持自定義配色方案、字體、大小和布局、支持音樂視頻,可以導出HTML和PDF。
MarkdownPad是獨立的軟件。
更多介紹及下載:http://markdownpad.com/
Typora也是非常用名,非常好用的markdown編輯器,它的設計理念很不一樣,是真正的即時預覽型編輯器,不同于左右兩個窗口的編輯器。Typora的設計理念就是極致簡潔,它將「寫字」和「預覽」這兩件事情合并了。
如果要修改已經寫好的markdown標記可以點擊切換到“源代碼模式”。
Typora 同樣支持 Windows、OS X 和 Linux多個操作系統,支持數學編輯,可與 Word 直接格式轉換,可以進行多種文檔格式轉換。Typora 流暢度和反應速度很快,特別適合那些手速快的人。
Typora是獨立的軟件。
更多介紹及下載:https://www.typora.io/
Atom 可以說是專門為程序員推出的一個文本編輯器,界面簡潔,支持實時預覽。功能非常多,除了Markdown同時支持CSS,HTML,JavaScript等網頁編程語言,還支持宏定義,自動分屏功能等。Atom還具有語義輸入模式,比例輸入code即會自動開啟代碼模式。
Atom支持windows、蘋果、linux等多種操作系統。Atom是由著名的github平臺出品的。
Atom是獨立的軟件,也支持插件方式。
更多介紹及下載:https://atom.io/
Haroopad也是一款非常流行的編輯器,來自韓國。Haroopad支持 Windows、Mac OS X 和 Linux三大操作系統。Haroopad的特色是主題樣式豐富,語法高亮支持無數種編程語言,幾乎你能想到的編程語言他都支持。Ubuntu/Linux 用戶使用該工具比例很高,Haroopad 也是開源免費的。Haroopad也支持導出HTML、PDF,也支持數學公式和流程圖。
Haroopad是獨立的軟件。
更多介紹及下載:http://pad.haroopress.com/user.html
SublimeText界面簡約大方,定位專業,功能強大,并具有良好的擴展功能。SublimeText是收費軟件,支持windows、蘋果、linux三大操作系統。支持的編程語言有十幾種,并可通過第三方插件無限擴充。
SublimeText默認不能實時預覽,但通過 Markdown Preview 的插件來實現該功能。SublimeText屏幕右邊有一個文檔縮略圖,可以看到文檔全貌。
SublimeText是獨立的軟件,也支持插件方式。
更多介紹及下載:http://www.sublimetext.com/
Cmd Markdown是一款不錯的寫作工具,同時也兼顧博客等寫作平臺,國內作業部落出品,同時支持Windows、蘋果、Linux操作系統,也有 Web 在線創作平臺,界面很舒服。
Cmd Markdown是獨立的軟件、也有平臺集成版本。
更多介紹及下載:https://www.zybuluo.com/mdeditor
Byword。一款輕量級的 Markdown 編輯器,比較容易上手,適合新手使用。支持蘋果系列系統,包括臺式機、iPad和iPhone,收費軟件。
Byword是獨立的軟件。
更多介紹及下載:https://bywordapp.com/
CuteMarkEd 是一個基于qt5的Markdown 編輯器,開源免費,支持windows、蘋果、linux多種系統平臺,提供實時 HTML 預覽、數學表達式、代碼高亮和PDF導出。
CuteMarkEd是獨立的軟件。
更多介紹及下載:https://cloose.github.io/CuteMarkEd/
Dillinger是國外的 Markdown 編輯器,Web在線創作。漂亮強大,支持md、 html、pdf 文件導出,支持Dropbox、Bitbucket、Github、Google Drive、Onedrive 一鍵保存,也可以編寫本地文件。支持實時預覽,跨平臺,瀏覽器打開。
Dillinger是平臺集成工具,不是獨立的軟件。
更多介紹及下載:https://dillinger.io/
11、EpicEditor
EpicEditor 是個嵌入式 JavaScript Markdown 編輯器,可以全屏編輯,在線預覽,自動草稿保存,支持離線等功能。對于開發者有很大吸引力,很容易集成在自己的系統中,并很容易自定義,也支持主題自定義。
EpicEditor屬于插件類的API工具。
更多介紹及下載:http://ww1.epiceditor.com/
MarkdownEditor是一款基于瀏覽器的 Markdown 編輯器,雖然他是獨立軟件,但該軟件內嵌一個瀏覽器。功能非常簡單實用、反應速度很快,號稱是Markdown領域的NotePad(記事本)。MarkdownEditor還有拼寫檢查功能。
MarkdownEditor有兩個版本,都是國人開發的,都是開源免費的。
MarkdownEditor是獨立的軟件、也有在線Web集成版。
更多介紹及下載:http://jbt.github.io/markdown-editor/
MarkPad是免費開源的 Markdown 編輯器,界面風格與window系統類似,同時只支持Window。支持實時預覽,開放直接保存到你的博客或github的接口,有語法檢查,支持代碼高亮。
MarkPad是獨立的軟件。
更多介紹及下載:http://code52.org/DownmarkerWPF/
Marxico中文名馬克飛象,有桌面版、Chrome App插件,也支持Web集成版。這款編輯器的特點是可以直接把文本存到印象筆記平臺中,另外還有導出HTML時可以將其中的圖片自動轉成base64保存。其他的實時預覽、語法高亮也都支持。
不過這款軟件是收費的~ ~
Marxico是獨立的軟件、同時有Chrome App插件,也支持Web集成。
更多介紹及下載:http://marxi.co/
實在太困了,就先介紹這么多吧~ ~ ~ (PS:剛接觸寫博客,發現還真是個累活呀:-P)
markdown編輯器產品非常多,以上只是本人接觸過的一些,相信還有很多很好的markdown存在,其實也沒必要全都試一遍,只有最適合自己的,才是最好的。
如果你用過其中的一種,或者你用過其他好用的markdown編輯器,歡迎交流分享。
覺這個特效對大神們來說簡直so so so so so easy!但我就是要要要要要要要要要發出來,分享給正在學習前端開發的朋友們,代碼在下文直接復制走,而且不用說謝謝~嘿嘿。時不時發一點好玩的特效,喜歡的朋友點一下上面的關注哦。我只是小小的前端開發工程師而已,各位大佬別噴我,謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝謝啦。(你還別說,這支付寶體真挺好玩。)
別噴我,比起讓你加群拿代碼的那些教育機構的推廣者,我連個廣告都沒打!
按下鍵盤上的A 網頁上的A就會動哦~
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>網頁鍵盤鋼琴按鍵特效</title>
<style>
*{
margin:0;
padding:0;
list-style:none;
}
#box{
width:400px;
margin:300px auto 0;
}
ul{
margin-right:-20px;
}
li{
width:48px;
height:48px;
border:1px solid #666;
float:left;
margin-right:20px;
text-align:center;
line-height:48px;
background:#000;
color:#fff;
font-weight:bold;
position:relative;
}
li span{
display:block;
opacity:0.5;
filter:alpha(opacity:50);
}
li p{
width:100%;
height:0;
background:#03F;
position:absolute;
bottom:49px;
left:0;
}
.keyA{
background:#e51c55;
}
.keyS{
background:#c926a5;
}
.keyD{
background:#9c4bd5;
}
.keyJ{
background:#4f65c3;
}
.keyK{
background:#6ccab7;
}
.keyL{
background:#92d55d;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li>
<span class="keyA">A</span>
<p class="keyA"></p>
</li>
<li>
<span class="keyS">S</span>
<p class="keyS"></p>
</li>
<li>
<span class="keyD">D</span>
<p class="keyD"></p>
</li>
<li>
<span class="keyJ">J</span>
<p class="keyJ"></p>
</li>
<li>
<span class="keyK">K</span>
<p class="keyK"></p>
</li>
<li>
<span class="keyL">L</span>
<p class="keyL"></p>
</li>
</ul>
</div>
<script>
window.onload=function(){
var aP=document.getElementsByTagName("p");
var aSpan=document.getElementsByTagName("span");
var aKeyCode=[65,83,68,74,75,76]; //定義鍵盤按鍵的鍵值 65表示大寫A 具體鍵值請參照文章里的ascii表里的值
document.onkeydown=function(event){
var event=event || window.event;
for(var i=0; i<aKeyCode.length; i++){
if(event.keyCode==aKeyCode[i]){
startMove(aP[i],{height:240});
startMove(aSpan[i],{opacity:100})
}
}
}
document.onkeyup=function(event){
var event=event || window.event;
for(var i=0; i<aKeyCode.length; i++){
if(event.keyCode==aKeyCode[i]){
startMove(aP[i],{height:0});
startMove(aSpan[i],{opacity:50})
}
}
}
}
function startMove(obj, json, fnEnd){
clearInterval(obj.timer);
obj.timer=setInterval(function (){
var bSwitch=true;
for(var sAttribute in json){
var iTarget=json[sAttribute];
if(sAttribute=='opacity'){
var cur=Math.round(parseFloat(getStyle(obj, sAttribute))*100);
}else{
var cur=parseInt(getStyle(obj, sAttribute));
}
var speed=(iTarget-cur)/5;
speed=speed>0?Math.ceil(speed):Math.floor(speed);
if(sAttribute=='opacity'){
obj.style.filter='alpha(opacity:'+(cur+speed)+')'; //IE
obj.style.opacity=(cur+speed)/100; //ff chrome
}else{
obj.style[sAttribute]=cur+speed+'px';
}
if(cur!=iTarget){
bSwitch=false;
}
}
if(bSwitch){
clearInterval(obj.timer);
if(fnEnd){
fnEnd();
}
}
}, 30);
}
//獲取飛行間樣式
function getStyle(obj,sAuttribute){
var result=""
if(window.getComputedStyle){
result=window.getComputedStyle(obj,false)[sAuttribute];
}else{
resule=obj.currentStyle[sAuttribute];
}
return result;
}
</script>
</body>
</html>
如果哪句代碼不理解,可以直接在下面留言,我看到了會一一解釋哦。當然啦,你噴我我也會回你。
喜歡JS特效的朋友,記得關注我哦,不定期分享好玩好看的JS特效,前端路上,一起成長~
*請認真填寫需求信息,我們會在24小時內與您取得聯系。