《從零開始, 開發一個 Web Office 套件》系列部落格目錄
這是一個系列部落格, 最終目的是要做一個基於HTML Canvas 的, 類似於微軟 Office 的 Web Office 套件, 包括: 文件, 表格, 幻燈片... 等等.
對應的Github repo 地址: https://github.com/zhaokang555/canvas-text-editor
2. 富文字編輯器(MVP)
2.13 z-index
2.13.1 新的問題
上一篇部落格中, 我們實現了mouse hover over SizeControlPoint的feature. 現在, 問題來了: SizeControlPoint和editor border會有重疊的部分, 當滑鼠hover到這個位置時, 應該怎麼處理?
我暫時想到了一種解決方案: 引入z-index
的概念, 為SizeControlPoint和editor border分配不同的z-index
. 當滑鼠hover到元素重疊的部分時, 尋找最大的z-index
對應的元素.
2.13.2 實現
修改src/core/ResponsiveToMouseHover.ts
:
- 新增屬性
zIndex
- constructor新增形參
options
, 用來設定zIndex
- 新增兩個靜態屬性
topLayerZIndex
和topLayerCursorType
, 用來記錄最上層圖層對應的zIndex
值和滑鼠樣式 - 修改render函式, 記錄
topLayerZIndex
和topLayerCursorType
同時, 修改src/core/SizeControlPoint.ts
, 讓它支援設定zIndex
:
最後, 修改src/coreCanvasTextEditor.ts
:
- 修改
render
函式, 在所有的sizeControlPoints
render結束之後, 再設定canvas.style.cursor
- 修改
clearCanvas
函式, 重置ResponsiveToMouseHover.topLayerZIndex
和ResponsiveToMouseHover.topLayerCursorType
2.14 Mouse hover over editor border
處理完z-index
的問題, 我們就可以實現這個feature了: 當滑鼠hover到編輯器邊緣的虛線邊框上時, 滑鼠形狀隨之變化
2.14.1 重構: Extract component: CanvasTextEditorBorder
新建檔案src/core/CanvasTextEditorBorder.ts
:
其中, Victor
是一個開源數學庫: http://victorjs.org/, 可以做一些二維向量計算, 可以通過npm安裝:
npm install victor --save
npm install @types/victor --save-dev
然後重構檔案src/core/CanvasTextEditor.ts
:
- 修改
constructor
, 抽出initParagraphs
和initSizeControlPoints
函式 - 新增
initBorder
函式, 並在constructor
中呼叫 - 刪除
renderBorder
函式 - 修改
render
函式
同時,修改CanvasTextEditor.destructor
, 在其中呼叫每個border例項的destructor
:
2.14.2 實現
實現這個feature之前, 我們需要思考如何擴充border的響應範圍(responsive zone). 為什麼要這樣呢? 因為border是一條很細的線, 要讓滑鼠精確地hover上去非常困難, 所以要擴大它的responsive zone. 如下圖所示, 我們把border橫向擴充, 灰色的範圍就是擴充後的responsive zone.
然後, 我們動手來實現. 修改src/core/CanvasTextEditorBorder.ts
:
- 繼承
ResponsiveToMouseHover
- 新增常量
borderResponsiveWidth
, 用來表示擴充後的responsive box的寬度 - 新增常量
defaultCanvasTextEditorBorderZIndex
, 用來表示border預設的zIndex
- 在
constructor
中:- 計算border的法向量
normalVector
- 然後計算
responsive zone
的四角座標, 存入points
中 - 然後利用四角座標, 計算
responsive zone
的left, top, width, height
, 傳入super()
中
- 計算border的法向量
上圖中,我們使用了Victor
(http://victorjs.org)這個二位向量運算庫的若干API:
.clone()
: 克隆一個二維向量,並返回.substract(vector)
: 用自己減去另一個二維向量,並將結果賦值給自己.add(vector)
: 用自己加上另一個二維向量,並將結果賦值給自己.rotate(angle)
: 將自己沿原點旋轉若干弧度,並將結果賦值給自己.normalize()
: 將自己標準化,並將結果賦值給自己.multiplyScalar(scalar)
: 將自己乘以一個數量,並將結果賦值給自己
同時, 在src/core/CursorType.ts
中, 新增十字滑鼠樣式(see: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor) :
2.14.3 效果
給responsive zone
加上灰色背景, 看一下它的範圍是否合適:
(未完待續)