從零開始,開發一個 Web Office 套件(8):狀態管理 & 拖動滑鼠選中文字

趙康發表於2022-03-10

這是一個系列部落格,最終目的是要做一個基於 HTML Canvas 的、類似於微軟 Office 的 Web Office 套件(包括:文件、表格、幻燈片……等等)。
部落格園:《從零開始, 開發一個 Web Office 套件》系列部落格目錄
富文字編輯器 Github repo 地址:https://github.com/zhaokang555/canvas-text-editor

2. 富文字編輯器 (MVP)

2.20 狀態管理

2.20.1 重構程式碼

在新增狀態管理之前,我們先來重構下程式碼。首先,將之前的兩個類改一下名字:

  • rename ResponsiveToMouseHover to HoverableZone
  • rename ClickZone to ClickableZone

然後,新建路徑src/core/mouse,將上面兩個類挪進來:

2.20.2 新增狀態管理

之前,我們的一些全域性狀態是以class static field的方式存在的。這樣做剛開始可能不會出現問題,但是到後面會出問題:

  • 狀態分散
  • 無法處理多個Editor例項的情形

所以,我們需要引入狀態管理。新建檔案src/core/Store.ts:

然後,修改CanvasTextEditor:

  • this.ctx => this.store.ctx
  • ClickableZone.* => this.store.mouse.click.*
  • HoverableZone.* => this.store.mouse.hover.*

同理,修改其它檔案。

2.21 拖動滑鼠選中文字

接下來,我們來實現拖動滑鼠,高亮選中文字的需求:

2.21.1 實現

首先,修改Store,新增以下欄位和方法:

  • chars: 編輯器內所有字元
  • mouse.select.beginCharmouse.select.endChar: 記錄選擇開始和結束的字元
  • getGlobalNextChargetGlobalPrevChar: 獲取跨行、跨段落的後/前一個字元
  • clearSelect: 清空選擇資訊
  • finishSelect:檢查需要高亮哪些字元
  • 其中Char.selectableZone.isSelect用來切換字元的高亮(選中)狀態,稍後實現

然後,修改Editor, 將編輯器內所有字元存入store:

然後,修改Char:

  • 新增欄位:leftHalf: HalfCharrightHalf: HalfChar,用來處理click, mousedown, mouseup 事件
  • 新增欄位:selectableZone: SelectableZone,表示高亮區域
  • 刪除欄位:leftClickableZonerightClickableZone,因為它們已經被整合進leftHalfrightHalf
  • 其中,HalfChar 稍後實現

然後,我們來補全實現。新建檔案src/core/mouse/SelectableZone.tssrc/core/CanvasTextEditorHalfChar.ts:

其中,MousedownZoneMouseupZone用來監聽滑鼠按下和彈起的事件。新建檔案src/core/mouse/MousedownZone.tssrc/core/mouse/MouseupZone.ts:

2.21.2 效果

不過,還有一些edge case, 我們下一小節再處理。

(未完待續)

相關文章