AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

圖形編輯器開發(fā):快捷鍵的管理

來源: 責(zé)編: 時間:2023-10-08 09:59:56 325觀看
導(dǎo)讀大家好,我是前端西瓜哥。快捷鍵操作在圖形編輯器中是很高頻的操作,能讓用戶快速高效地執(zhí)行特定命令。那么今天就來學(xué)習(xí)圖形編輯器是如何做快捷鍵的管理的。編輯器 github 地址:https://github.com/F-star/suika線上體驗:h

UZX28資訊網(wǎng)——每日最新資訊28at.com

大家好,我是前端西瓜哥。UZX28資訊網(wǎng)——每日最新資訊28at.com

快捷鍵操作在圖形編輯器中是很高頻的操作,能讓用戶快速高效地執(zhí)行特定命令。UZX28資訊網(wǎng)——每日最新資訊28at.com

那么今天就來學(xué)習(xí)圖形編輯器是如何做快捷鍵的管理的。UZX28資訊網(wǎng)——每日最新資訊28at.com

圖片UZX28資訊網(wǎng)——每日最新資訊28at.com

編輯器 github 地址:UZX28資訊網(wǎng)——每日最新資訊28at.com

https://github.com/F-star/suikaUZX28資訊網(wǎng)——每日最新資訊28at.com

線上體驗:UZX28資訊網(wǎng)——每日最新資訊28at.com

https://blog.fstars.wang/app/suika/UZX28資訊網(wǎng)——每日最新資訊28at.com

簡單的快捷鍵綁定

我們先看看原生的鍵盤事件能否滿足需求。UZX28資訊網(wǎng)——每日最新資訊28at.com

假設(shè)我們需要判斷用戶是否按下了 Ctrl + C(需要精準(zhǔn)匹配),如果按下了就執(zhí)行 copy 方法。UZX28資訊網(wǎng)——每日最新資訊28at.com

用原生事件,我們要這樣寫:UZX28資訊網(wǎng)——每日最新資訊28at.com

window.addEventListener('keydown', (e) => {  const { ctrlKey, shiftKey, altKey, metaKey } = e;  if (ctrlKey && !shiftKey && !altKey && !metaKey && e.code === 'KeyC') {    copy();  }})

寫法有點繁瑣。我們希望能簡化一下寫法。UZX28資訊網(wǎng)——每日最新資訊28at.com

一開始我并不太在意快捷鍵綁定的管理,因為復(fù)雜度還沒起來,就找了一個輪子 hotkeys-js。UZX28資訊網(wǎng)——每日最新資訊28at.com

import hotkeys from 'hotkeys-js';hotkeys('ctrl+c', copy);

hotkeys-js 是原生事件的一層簡單的封裝,簡化了寫法并提高了可讀性。UZX28資訊網(wǎng)——每日最新資訊28at.com

如果你的圖形編輯器并不復(fù)雜,用一些易用性不錯的快捷鍵庫是不錯的選擇。UZX28資訊網(wǎng)——每日最新資訊28at.com

快捷鍵高級能力

原生事件和一些常見的快捷鍵庫可以處理一些簡單的場景,但圖形編輯器的場景往往更復(fù)雜。UZX28資訊網(wǎng)——每日最新資訊28at.com

圖形編輯器還需要的快捷鍵高級能力有:UZX28資訊網(wǎng)——每日最新資訊28at.com

  • 給一個行為設(shè)置多個不同快捷鍵,比如 Delete 或 Backspace 都可以刪除選中元素(這個大多第三方快捷鍵輪子是支持的);
  • 可以根據(jù)不同操作系統(tǒng)綁定不同的快捷鍵,比如復(fù)制,我希望在 Windows 系統(tǒng)為 Ctrl+C,在 MacOS 系統(tǒng)則是 Command+C。
  • 提供環(huán)境上下文,綁定的函數(shù)可以通過它決定是否被調(diào)用,比如我希望移動圖形的時候不能執(zhí)行 Delete 對應(yīng)刪除操作。
  • 支持短路匹配,只執(zhí)行第一個匹配條件。這是為了防止快捷鍵沖突,一個快捷鍵執(zhí)行了多個行為。當(dāng)然如果你就是希望一個快捷鍵要執(zhí)行多個行為,那可以考慮補(bǔ)充一個 next 方法。
  • 某個快捷鍵綁定可以設(shè)置為高優(yōu)先級,比如激活某個工具時,要注冊一些快捷鍵,需要高優(yōu)先級,以便覆蓋掉和其他的同名快捷鍵。

快捷鍵管理類

考慮上面這些功能點,我們來實現(xiàn)這個快捷鍵管理類 KeyBindingManager。UZX28資訊網(wǎng)——每日最新資訊28at.com

class KeyBindingManager {  // 傳入一個入口類對象 Editor,之后需要用到它的變量  constructor(private editor: Editor) {}}

keyBinding 對象

一份快捷鍵綁定(keyBinding)由下面幾個部分組成:UZX28資訊網(wǎng)——每日最新資訊28at.com

key,快捷鍵描述。理論上應(yīng)該用 "Ctrl+C" 這種字符串來描述,但它實現(xiàn)起來比較麻煩,要解析,要轉(zhuǎn)換(比如 / 要轉(zhuǎn)成 Slash 去匹配 event.code)。UZX28資訊網(wǎng)——每日最新資訊28at.com

所以我換成了一個對象:{ CtrlKey: true, keyCode: 'KeyC' }。不用解析,不用轉(zhuǎn)換,直接和 event 的屬性對比即可。這個是 精準(zhǔn) 匹配,即不能有多余的修飾鍵。UZX28資訊網(wǎng)——每日最新資訊28at.com

此外,key 也支持傳入數(shù)組,這種情況比較少,對應(yīng)一個行為有多個快捷鍵的情況。比如刪除操作,我們可以傳入 [{ keyCode: 'Delete' }, { keyCode: 'Backspace' }]。UZX28資訊網(wǎng)——每日最新資訊28at.com

winKey,快捷鍵描述(Windows 特供版)。這個參數(shù)是可選的,如果不提供,所有系統(tǒng)都會使用 key 參數(shù)。如果提供,且用戶操作系統(tǒng)為 Windows,會使用  winKey,忽略 key。UZX28資訊網(wǎng)——每日最新資訊28at.com

when,是否滿足上下文。也是可選的。when 是一個方法,可以通過它拿到一些上下文參數(shù),通過這些參數(shù)決定返回的布爾值。如果為 true,表示匹配到了,并執(zhí)行對應(yīng)的響應(yīng)行為;如果為 false,沒匹配到,繼續(xù)找下一個。when 可不提供,表示永遠(yuǎn)滿足條件。UZX28資訊網(wǎng)——每日最新資訊28at.com

action,快捷鍵匹配后要執(zhí)行的方法。UZX28資訊網(wǎng)——每日最新資訊28at.com

TypeScript 類型簽名為:UZX28資訊網(wǎng)——每日最新資訊28at.com

interface IKeyBinding {  key: IKey | IKey[];  winKey?: IKey | IKey[];  when?: (ctx: IWhenCtx) => boolean;  action: (e: KeyboardEvent) => void;}interface IKey {  ctrlKey?: boolean;  shiftKey?: boolean;  altKey?: boolean;  metaKey?: boolean;  // KeyboardEvent['code'] 或 '*'(匹配任何按鍵)  keyCode: string;}interface IWhenCtx {  isToolDragging: boolean; // 是否在拖拽中(比如移動工具移動圖形中)}

快捷鍵注冊

我們需要用有序表來根據(jù)注冊順序保存 keyBinding 的,這里我選擇用 Map 數(shù)據(jù)結(jié)構(gòu),它是一種有序數(shù)據(jù)結(jié)構(gòu)。UZX28資訊網(wǎng)——每日最新資訊28at.com

class KeyBindingManager {  // 用 Map   private keyBindingMap = new Map<number, IKeyBinding>();  private id = 0;    //...   // 注冊一個快捷鍵  register(keybinding: IKeyBinding) {    const id = this.id;    this.keyBindingMap.set(id, keybinding);    this.id++;    return id;  }    // 注銷快捷鍵  unregister(id: number) {    this.keyBindingMap.delete(id);  }}

注冊方法 register 會返回一個唯一 id,如果需要注銷,需要將這個 id 傳給注銷方法 unregister。UZX28資訊網(wǎng)——每日最新資訊28at.com

事件的解綁方式有 3 種,這里選擇的是類似 setTimeout 返回一個訂閱 id 的風(fēng)格。UZX28資訊網(wǎng)——每日最新資訊28at.com

《事件訂閱的幾種實現(xiàn)風(fēng)格》UZX28資訊網(wǎng)——每日最新資訊28at.com

實際上 3 種寫法都沒啥差別,都是要把綁定事件方法返回的結(jié)果保存下來,在合適的時機(jī)調(diào)用解綁方法。UZX28資訊網(wǎng)——每日最新資訊28at.com

哦對了,還有注冊高優(yōu)先級快捷鍵的方法:UZX28資訊網(wǎng)——每日最新資訊28at.com

class KeyBindingManager {  // ...    // 綁定一個高優(yōu)先級快捷鍵綁定(會放到 Map 的開頭)  registerWithHighPrior(keybinding: IKeyBinding) {    const id = this.id;    const map = new Map<number, IKeyBinding>();    map.set(id, keybinding);    for (const [key, val] of this.keyBindingMap) {      map.set(key, val);    }    this.keyBindingMap = map;    this.id++;    return id;  }}

其實就是把這個快捷鍵注冊到 Map 的開頭。UZX28資訊網(wǎng)——每日最新資訊28at.com

如果你需要更細(xì)的粒度,比如低優(yōu)先級、中優(yōu)先級、高優(yōu)先級,那你可以考慮傳多一個優(yōu)先級枚舉值或一個數(shù)值,然后在正確的位置插入。感覺并沒有太多需要用到這種粒度的場景。UZX28資訊網(wǎng)——每日最新資訊28at.com

短路匹配邏輯

然后就是快捷鍵的匹配邏輯:UZX28資訊網(wǎng)——每日最新資訊28at.com

  • 匹配順序根據(jù)注冊順序(有特例,就是前面說的高優(yōu)先級快捷鍵綁定,會插隊,插到隊伍開頭)。
  • 使用精準(zhǔn)匹配(key 或 winKey),以及 when 方法是否為 true,都為 true 時執(zhí)行 action。
  • 使用短路邏輯,即只執(zhí)行第一個匹配的(后面可能也有其他匹配的,但不執(zhí)行)。這個其實是設(shè)計模式的責(zé)任鏈模式,像是 express 或 koa 的路由匹配機(jī)制也是責(zé)任鏈模式。

實現(xiàn)如下:UZX28資訊網(wǎng)——每日最新資訊28at.com

const isWindows =  navigator.platform.toLowerCase().includes('win') ||  navigator.userAgent.includes('Windows');class KeyBindingManager {    // ...    // 綁定到原生鍵盤按下事件上  bindEvent() {    if (this.isBound) return;    this.isBound = true;    document.addEventListener('keydown', this.handleAction);  }    // 找到匹配的 keyBinding,執(zhí)行其 action  private handleAction = (e: KeyboardEvent) => {    if (      e.target instanceof HTMLInputElement ||      e.target instanceof HTMLTextAreaElement    ) {      return;    }    let isMatch = false;        // 生成上下文對象,可根據(jù)需要擴(kuò)充    const ctx: IWhenCtx = {      isToolDragging: this.editor.toolManager.isDragging,    };    for (const keyBinding of this.keyBindingMap.values()) {      // 先看看 when 是否為 true(when 可不提供)      if (!keyBinding.when || keyBinding.when(ctx)) {        // 如果是 Windows 操作系統(tǒng),看看 winKey 對不對        if (isWindows) {          if (keyBinding.winKey && this.isKeyMatch(keyBinding.winKey, e)) {            isMatch = true;          }        }        // 其他操作系統(tǒng),看 key 是否匹配        else if (this.isKeyMatch(keyBinding.key, e)) {          isMatch = true;        }      }      // 匹配      if (isMatch) {        e.preventDefault();        keyBinding.action(e); // 執(zhí)行對應(yīng) action(行為)        break; // 結(jié)束,不繼續(xù)遍歷      }    }  };  private isKeyMatch(key: IKey | IKey[], e: KeyboardEvent): boolean {    if (Array.isArray(key)) {      return key.some((k) => this.isKeyMatch(k, e));    }    if (key.keyCode == '*') return true;    const {      ctrlKey = false,      shiftKey = false,      altKey = false,      metaKey = false,    } = key;    return (      ctrlKey == e.ctrlKey &&      shiftKey == e.shiftKey &&      altKey == e.altKey &&      metaKey == e.metaKey &&      key.keyCode == e.code    );  }}

用法舉例

類寫好了,看看用法。UZX28資訊網(wǎng)——每日最新資訊28at.com

刪除快捷鍵的寫法:UZX28資訊網(wǎng)——每日最新資訊28at.com

const deleteAction = () => {  // 刪除選中元素};editor.keybindingManager.register({  // Backspace 或 Delete 都可以刪除  key: [{ keyCode: 'Backspace' }, { keyCode: 'Delete' }],  // 只能在沒有發(fā)生拖拽的情況下下刪除(比如移動圖形時不能刪除)  when: (ctx) => !ctx.isToolDragging,  action: deleteAction,});

復(fù)制快捷鍵的寫法:UZX28資訊網(wǎng)——每日最新資訊28at.com

const copyHandler = () => {  // 復(fù)制}editor.keybindingManager.register({  key: { metaKey: true, keyCode: 'KeyC' },  // Windows 環(huán)境下的快捷鍵  winKey: { ctrlKey: true, keyCode: 'KeyC' },  action: copyHandler,});

一些優(yōu)化點

  • 如果你考慮一些非美式鍵盤,比如法語鍵盤,因為按鍵布局位置發(fā)生了變化,需要做鍵位的重映射,確保物理位置不變,確保用戶的肌肉記憶有效。
  • 簡化快捷鍵描述的寫法,使用類似 Ctrl+/ 的更簡潔寫法。如果你需要類似 VSCode 一樣提供 JSON 文件給支持用戶自己設(shè)置快捷鍵,這個還是要實現(xiàn)的。

本文鏈接:http://www.tebozhan.com/showinfo-26-12425-0.html圖形編輯器開發(fā):快捷鍵的管理

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: HTTP協(xié)議揭秘:探尋互聯(lián)網(wǎng)的背后密碼、探秘數(shù)據(jù)傳輸?shù)膴W秘

下一篇: 一個 println 竟然比 volatile 還好使?

標(biāo)簽:
  • 熱門焦點
  • 中興AX5400Pro+上手體驗:再升級 雙2.5G網(wǎng)口+USB 3.0這次全都有

    2021年11月的時候,中興先后發(fā)布了兩款路由器產(chǎn)品,中興AX5400和中興AX5400 Pro,從產(chǎn)品命名上就不難看出這是隸屬于同一系列的,但在外觀設(shè)計上這兩款產(chǎn)品可以說是完全沒一點關(guān)系
  • 印度登月最關(guān)鍵一步!月船三號今晚進(jìn)入環(huán)月軌道

    8月5日消息,據(jù)印度官方消息,月船三號將于北京時間今晚21時30分左右開始近月制動進(jìn)入環(huán)月軌道。這是該探測器能夠成功的最關(guān)鍵步驟之一,如果成功將開始圍
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 企業(yè)采用CRM系統(tǒng)的11個好處

    客戶關(guān)系管理(CRM)軟件可以為企業(yè)提供很多的好處,從客戶保留到提高生產(chǎn)力。  CRM軟件用于企業(yè)收集客戶互動,以改善客戶體驗和滿意度。  CRM軟件市場規(guī)模如今超過580
  • 學(xué)習(xí)JavaScript的10個理由...

    作者 | Simplilearn編譯 | 王瑞平當(dāng)你決心學(xué)習(xí)一門語言的時候,很難選擇到底應(yīng)該學(xué)習(xí)哪一門,常用的語言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • 之家push系統(tǒng)迭代之路

    前言在這個信息爆炸的互聯(lián)網(wǎng)時代,能夠及時準(zhǔn)確獲取信息是當(dāng)今社會要解決的關(guān)鍵問題之一。隨著之家用戶體量和內(nèi)容規(guī)模的不斷增大,傳統(tǒng)的靠"主動拉"獲取信息的方式已不能滿足用
  • 谷歌KDD'23工作:如何提升推薦系統(tǒng)Ranking模型訓(xùn)練穩(wěn)定性

    谷歌在KDD 2023發(fā)表了一篇工作,探索了推薦系統(tǒng)ranking模型的訓(xùn)練穩(wěn)定性問題,分析了造成訓(xùn)練穩(wěn)定性存在問題的潛在原因,以及現(xiàn)有的一些提升模型穩(wěn)定性方法的不足,并提出了一種新
  • 東方甄選單飛:有些鳥注定是關(guān)不住的

    作者:彭寬鴻來源:華爾街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;東方甄選創(chuàng)始人俞敏洪帶隊的&ldquo;7天甘肅行&rdquo;直播活動已在近日順利收官。成立后一
  • 國行版三星Galaxy Z Fold5/Z Flip5發(fā)布 售價7499元起

    2023年8月3日,三星電子舉行Galaxy新品中國發(fā)布會,正式在國內(nèi)推出了新一代折疊屏智能手機(jī)三星Galaxy Z Fold5與Galaxy Z Flip5,以及三星Galaxy Tab S9
Top