天天看點

擴充HT for Web之HTML5表格元件的Renderer和Editor

slider:拉條

color picker:顔色選擇器

enum:枚舉類型

boolean:真假編輯器

string:普通的文本編輯器

除了這幾種常用編輯器之外,使用者還可以通過繼承ht.widget.BaseItemEditor類來實作自定義編輯器。

color:顔色類型

boolean:真假渲染器

text:文本渲染器

和編輯器一樣也可以自定義渲染器,但是方式不太一樣,渲染器是通過定義column中drawCell()方法來自定義單元格展現效果。

首先來瞧瞧效果:

擴充HT for Web之HTML5表格元件的Renderer和Editor

效果圖中,左邊表格的第二列,是定義了一個編輯器,用一個圓盤來表示目前文本的旋轉角度,可以通過拖拉來實作角度變換;表格的第三列,是通過drawCell()方法來繪制單元格内容,中間線辨別旋轉角度為零,向左表示文本逆時針旋轉指定角度,向右表示文本順時針旋轉指定角度。

接下來我們就來看看具體的實作,先來了解下渲染器的實作:

上面的代碼就是定義表格第三列的代碼,可以看到除了定義column自身屬性外,還添加了drawCell()方法,通過drawCell()方法傳遞進來的參數,來繪制自己想要的效果。

渲染就是這麼簡單,那麼編輯器就沒那麼容易了,在設計自定義編輯器之前,得先來了解下編輯器的基類ht.widget.BaseItemEditor,其代碼如下:

它處理構造函數中初始化類變量外,就定義了幾個接口,讓使用者重載實作相關業務操作邏輯處理。那麼接下來說說這些接口的具體用意:

editBeginning:在單元格開始編輯前調用

getView:擷取編輯器view,值類型為DOM元素

getValue:擷取編輯器值

setValue:設定編輯器值,并做編輯器的頁面初始化操作

在建立一個自定義編輯器的時候,必須實作這些接口,并在不同的接口中,做不同的操作。

現在我們來看看旋轉角度的自定義編輯是如何設計的:

2. editor需要與使用者有互動,是以,需要在view上添加事件監聽,監聽使用者有可能的操作,在這次的Demo中,我們希望使用者通過拖拉角度控制盤來控制角度,是以,我們在view上添加了mousedown、mousemove及mouseup三個事件監聽;

以上講述的操作都在構造函數中處理,接下來看看構造函數長什麼樣:

4. 接下來就是通過def()方法來定義ht.widget.RotationEditor類繼承于ht.widget.BaseItemEditor,并實作父類的方法,代碼如下,在代碼中,我沒有貼出setValue()方法的實作,因為這塊有些複雜,我們單獨抽出來講解;

5. 我們要在setValue()方法中繪制出文章開頭的效果圖上面展現的效果,大緻分解了些,可以分成以下四步來繪制,當然在繪制之前需要線獲得canvas的context對象:

    5.1. 繪制内外圓盤,通過arc()方法繪制兩個間隔10px的同心圓;

    5.2. 繪制值區域,通過結合arc()方法及lineTo()方法繪制一個扇形區域,在通過fill方法填充顔色;

    5.3. 繪制指針,通過lineTo()方法繪制兩個指針;

    5.4. 繪制文本,在繪制文本的時候,不能直接将文本繪制在圓心處,因為圓心處是指針的交彙處,如果直接繪制文本的話,将與指針重疊,這時,通過clearRect()方法來清除文本區域,在通過fillRect()方法将背景填充上去,不然文本區域塊将是透明的,接下來就調用fillText()方法繪制文本。

這些就是元件繪制的所有邏輯,但是有一點必須注意,在繪制完元件後,必須調用下restore()方法,因為在initContext()方法中做了一次save()操作,接下來看看具體實作(代碼有些長);

6. 這時候編輯器的設計就大體完成,那麼編輯器該如何用到表格上呢?很簡單,在表格定義列的時候,加上下面兩行代碼就可以開始使用編輯器了;

7. 在構造函數中,view的mousemove事件調用了startDragging()方法,其實這個方法是有依賴的,它需要元件重載handleWindowMouseMove()及handleWindowMouseUp()兩個方法。原因很簡單,就如第3點種提到的,使用者在拖拉元件的時候,有可能拖離了元件區域,這時候隻能通過window上的mousemove及mouseup兩個事件監聽令使用者繼續操作;

加上上面的三個方法,運作代碼可以發現編輯器可以正常編輯了。但是隻有在結束編輯後,才可以在拓撲圖上看到文本旋轉角度變化,如果可以實時更新拓撲圖上的文本旋轉角度,将會更加直覺些,那麼現在該怎麼辦呢?

8. 自定義編輯器這塊并像其他已經實作了的編輯器那樣可以指定編輯器的屬性,自定義編輯器能夠指定的就隻有一個類名,是以在編輯器上設定參數是沒用的,使用者無法設定到編輯器中。一個偷巧的方法是在column上做手腳,借鑒其他編輯器的設計思想,在column上添加一個名字為_instant的屬性,在代碼中通過該屬性值來判斷是否要立即更新對應的屬性值,是以隻需要在setValue()方法中添加如下代碼,就能夠實作實時更新屬性值的效果;

9. 至此,編輯器的設計已經完成,現在來看看具體的用法,下面的代碼是Table中具體的列定義,在列定義中,指定itemEditor屬性值,并設定_instant屬性為true,就可以實作編輯器實時更新的效果

代碼中你會發現定義了一個formatValue()方法,該方法是為了與編輯器中編輯的值類型一緻,都将弧度轉換為角度。

介紹下ms_listener子產品,如果類添加了ms_listener子產品,那麼在類中将會多以下兩個方法:

addListeners:将類中定義的handle_XXX()方法(XXX代表某個DOM事件名稱,如:mousemove等)作為相應的事件監聽函數添加到元件的view上;

removeListeners:将類中定義的handle_XXX()方法對應的事件從view上移除。

那麼類中如何添加ms_listener子產品呢,隻需要在def()方法中類的方法定義上,添加ms_listener:true這行代碼,并在方法定義上添加DOM事件對應的handle函數,再在構造函數中調用類的addListeners()方法。

具體的代碼我就不在闡述了,思路與前面講述的編輯器的思路差不多。

最後附上程式的所有代碼,供大家參考,有什麼問題歡迎留言咨詢。

繼續閱讀