【開源我寫的富文本】打造全網最勁富文本系列之大話技術難點與特點設計。

文章開始前先上個圖:css

大話富文本技術概要:html

  在web領域,一提到富文本,大夥都以爲很高深,很難,很複雜。可是若是你看了我這篇簡短的技術分析,你會發現其實富文本不算高深,稱不上很難,只是比較複雜,須要用點心,折騰幾次你也能作一個富文本編輯器。下面我將採用「問題+答疑」方式聊聊web端富文本。git

 

問題1、富文本是怎麼造成的?web

  有網友在切換【源碼】狀態下看到一大堆html + css修飾時,居然向我提問:「怎麼是這樣的一堆東西?」。網友很驚訝,我也很驚訝。做爲一個web開發者,寫不了富文本,那也不至於不瞭解web富文本的構成吧!因此我以爲有必要聲明一下這個基礎知識:web富文本是由html標籤 + css修飾造成的 !君不信,能夠去翻看ueditor、tinyMCE、kingEditor等等富文本編輯器。算法

 

問題2、富文本既然是html + css修飾造成的,那怎麼作才能根據用戶操做進行修飾呢?chrome

回答這個問題,須要從兩方面來解析:json

一、JavaScript腳本是如何知道用戶光標所在的選區?canvas

  答案:range對象。後端

  每一個瀏覽器中的window對象之下都存在一個range對象。range對象存放着當前光標所在的選區信息。現代瀏覽器(IE十、chrome、firefox)對range的支持都很良好,若是是舊版本的ie瀏覽器,range對象的獲取,其內部的某些api可能有不一樣的差別,須要作兼容性處理。根據range對象得到選區信息是開發者操控選區html內容的第一個步驟。api

二、獲得了選區後,如何進行css修飾,好比修飾color=「red」?

  這能夠說是富文本技術實現的麻煩之處(難點)。玩過富文本技術的同窗,確定會想到「document.execCommand()」這個大名鼎鼎的對象。目前市面上的富文本基本都是基於這個對象打造。好比對選區執行一個加粗修飾,你能夠直接調用「document.execCommand('bold')」。該API會將用戶選擇的文本都加上一個"strong"標籤。

  然而,document.execCommand不是萬能的,好比不支持插入文件、視頻,行高、邊距修飾等。因此基於這個api的富文本都必須擴展execCommand接口。execCommand除了支持有限外,還有個很使人不爽的地方,其執行的修飾並不符合web規範的要求,好比加粗採用「strong」標籤,而不是css修飾裏的「font-weight:bold」,並且屢次修飾操做會產生N層嵌套。基於execCommand打造的富文本能夠說沒有規律而言。其輸出的html內容,不適用於後端轉word、pdf等需求場景。

 

問題3、execCommand是富文本技術的核心,但也是周身缺點,請問有何良方?

  良方:依靠range,提取用戶選擇的文本,將文本採用span標籤包裝,而後採用標準的css對span標籤進行修飾!

 

問題4、良方思想很好,實現上有什麼難點嗎?

  難點確定有,並且須要一些巧妙的設計及實現。

  一、選區丟失問題

    選區丟失問題,execCommand方案一樣存在。表現爲:用戶劃選了選區,當點擊修飾按鈕時候,因爲瀏覽器的鼠標焦點機制,選區丟失了,形成點擊事件的修飾功能找不到選區。

    解決辦法:利用編輯器區域的mouseleave,修飾按鈕的mousedown、mouseup組合應用對選區進行暫存和恢復。

  二、span標籤組裝問題

     span標籤組裝?是什麼意思呢?請看下面一個選區demo,用戶劃選的內容是跨元素節點的複雜選區。

    

     用戶劃選的區域,覆蓋了先後兩個span、中間一個純文本。根據修飾需求,須要對 「節點中間內容結束」 這個劃選的內容進行加粗。那麼須要將上述選區轉爲span包裝後利用css修飾:

    

     從上述demo,能夠看出用戶劃選的內容多是一個標籤內的,也多是跨多個標籤而造成的。開發者須要編寫一個算法將劃選內容提取組裝爲多個span水平包裝的結構。

  三、span水平包裝算法實現要點

    根據range對象的collapsed屬性判斷是不是跨標籤選區。

    1)非跨標籤選區:根據range.startOffset、range.endOffset拆份內容造成一個數組,而後對每一個數組的內容進行span包裝。

    2)跨標籤選區:根據range.startContainer、range.endContainer、range.startOffset、range.endOffset,將內容進行拆分,並將拆分後的內容進行span包裝。

  四、span包裝引發的選區丟失恢復問題

    在span包裝的算法中,因爲須要對dom節點進行刪除、插入,會引發選區丟失。故須要在進行span組裝前,將當期選區的信息暫存起來,組裝好span後,根據暫存信息進行選區恢復。

算法思想總結

  一、利用range對象獲取用戶選區信息。

  二、根據range信息,將用戶選擇的內容進行拆分組合,造成水平結構的span包裝。

  三、上述算法中,因爲焦點變化,dom刪除插入的影響,存在選區丟失的問題,須要將選區信息暫存,並在適當時候恢復選區。

 

特點功能設計實現思想

  在bui-editor富文本中,提供了比較有特點的 「浮動文本、圖片」,左右邊距拖動調整,流程圖繪製等特點功能。下面介紹一下這些特點功能的實現。

  浮動文本/圖片功能

    1.web開發者都知道,html的浮動是利用position:absolute來實現的,absolute要求父元素是relatvie或者absulote。bui-editor一樣是利用這個技術點來實現浮動文本/圖片需求。

    2.bui-editor中會將編輯區域用一個聲明瞭relative的div進行包裝,在這個包裝div之下,是存放段落的div和浮動的div,這樣從結構設計上知足段落的流式佈局,又知足了浮動的需求。

    3.編輯區域內既然已經存在了流式段落div和浮動div,那麼須要對這兩種不一樣的div內容分別作處理。

  左右邊距拖動調整功能

    邊距拖動:利用range選區提取當前覆蓋的段落,經過拖動兩邊的邊線,調整段落的margin-left、width進行實現段落左右邊距的調整。

  流程圖繪製功能

    流程圖功能:利用bui-flow設計器繪製好流程,經過canvas技術導出base64位的圖片數據,而後插入到富文本中。富文本中將流程圖的json數據保存起來並實現流程圖的可編輯。

 

富文本結構設計

  目前市面上的富文本幾乎都是利用execCommand api來實現,這個api輸出的富文本html結構是混亂的(標籤不規範、N層嵌套、非css修飾)。這樣的富文本結構限制了富文本應用的後端擴展,難以實現word、pdf的轉換。爲此,bui-editor對富文本的輸出結構作了規範化的定義:

  一、段落結構採用div標籤,爲何不採用p標籤呢?p標籤是一個內容標籤,而咱們的段落內還存在table(表格),採用p標籤不符合w3c規範了。

  二、段落內採用水平化的span子標籤,利用span子標籤包裝內容,這樣便於將修飾設置到span標籤上,同時水平化的結構避免了嵌套的問題。

  三、段落div內除了span子標籤,還存在table標籤、image標籤、pre代碼塊標籤的可能性。

  四、table單元格內採用p標籤做爲單元格內的基本輸入單位,這樣能夠解決單元格內回車換行的需求。

  

技術要點總結:

  一、掌握range對象

  二、理解選區丟失的場景、緣由,及其對應策略

  二、實現span拆分包裝算法

  四、設計好富文本的html結構,拋棄execCommand Api

 

我相信,若是你對上述要點都有了理解,只要你願意多動幾回手,開發富文本不是個很難的事情。

 

歡迎訪問項目: https://gitee.com/kevin-huang/Bui-Editor-public

 

歡迎訪問我正在開發的流程設計器demo :  http://www.vvui.net/flow/index.html

相關文章
相關標籤/搜索