快速開發基於 HTML5 網絡拓撲圖應用之 DataBinding 數據綁定篇

前言

發現你們對於我從 json 文件中直接操做節點屬性來控制界面的動態變化感到比較好奇,因此這篇就針對數據綁定以及如何使用這些綁定的數據作一篇說明,我寫了一個簡單的例子,基於機房工控的服務器上設備的燈閃爍現象。咱們從 2d 和 3d 兩個角度來分析數據綁定的問題。html

效果圖

2djson

代碼實現

其實不論是 2d 仍是 3d,在 HT 中,數據綁定不分維度的,因此二者在實現上很是相似。數組

代碼下載地址:https://download.csdn.net/download/u013161495/10290996bash

繪製設備

2d 和 3d 中的設備都是基於下面這張用「矢量」繪製的一個機櫃內部設備,而且對這個矢量的「閃爍燈」部分加了數據綁定,具體綁定了「閃爍燈」的背景顏色以及陰影顏色,改變陰影顏色是爲了讓「燈」有「發光」的效果,下圖中的紅色方框即爲「閃爍燈」。服務器

首先咱們必須清楚如何繪製矢量(http://hightopo.com/guide/guide/core/vector/ht-vector-guide.html)?咱們這個 Demo 的總體的矢量繪製比較複雜,我就只說一下上圖中的「燈」矩形框和文本是怎麼繪製的。dom

咱們知道,繪製一個矢量 json 必須包含如下三個參數:異步

  • width 矢量圖形的寬度
  • height 矢量圖形的高度
  • comps 矢量圖形的組件 Array 數組,每一個數組對象爲一個獨立的組件類型(http://hightopo.com/guide/guide/core/vector/ht-vector-guide.html#ref_type),數組的順序爲組件繪製前後順序 每一個元素確定都是要寬度和高度的,這兩個屬性不作說明,comps 這個屬性卻是挺厲害的,上面第三點中提到了,這是一個數組,繪製圖形和文本的實際操做以下:
{
    "width": 48,//矢量總體寬度
    "height": 262,//矢量總體高度
    "comps": [
    {
        "type": "text",//文本
        "text": "端口3",//文本內容
        "align": "center",//文本對齊方式
        "color": "rgb(255,255,255)",//字體顏色
        "font": "8px arial, sans-serif",//文本字體大小
        "rect": [//組件繪製在矢量中的矩形邊界
            18.28654,//x 軸座標
            39.80679,//y 軸座標
            27.82265,//width
            11.5434//height
        ]
    },
    {
        "type": "rect",//矩形
        "background": "rgb(255,0,0)",//屬性默認值"shadow": true,//設置爲true顯示陰影"shadowOffsetX": 0,//選中圖元的陰影水平偏移
        "shadowOffsetY": 0,//選中圖元的陰影垂直偏移
        "rect": [//組件繪製在矢量中的矩形邊界
            4.38544,//x 軸座標
            32.55505,//y 軸座標
            14.46481,//width
            6.1554//height
        ]
    }]  
}
複製代碼

這段代碼繪製了一個矩形和一個文本。ide

繪製完矢量以後,咱們就能夠經過給節點設置圖片的方式來顯示這個矢量。固然上面繪製的矢量並非所有的繪製矢量的代碼,具體內容請參考:download.csdn.net/download/u0…函數

要動態改變一個節點的屬性,那麼確定要先獲取到這個節點,咱們能夠經過遍歷數據模型 DataModel,或者經過 tag 標籤獲取節點,又或者經過鼠標點擊事件等等。這個 Demo 中須要操做的節點比較多,因此我選擇用遍歷數據模型的方法來獲取節點。那麼問題來了,我怎麼經過一張圖片或者一個矢量定位這個節點?若是節點都沒有建立,也不可能獲取到圖片對應的節點(或者說若是直接把這個矢量圖拿來做爲一個節點的圖片,有可能出現的狀況就是,六個設備的變化狀況都如出一轍!畢竟是同一個節點!)。因此咱們得把這些特殊的部分從圖片中刪除掉,而後在對應的位置填充上節點,再給節點設置上設備的矢量圖。先把對應位置的矢量圖刪除掉,以下圖紅框部分:字體

咱們在紅框部分單首創建八個設備節點,並給這八個節點分別設置同一張矢量圖。誒?你可能會詫異爲何同一張圖顯示卻不一樣(燈亮的變化順序不一樣),下面咱們來看看這是怎麼完成的。

那麼這八個擁有相同矢量圖的設備是如何經過代碼控制閃爍燈隨機變化的呢?關鍵就在咱們上面繪製的矢量圖中,前面有意略過了這部分:數據綁定。

數據綁定

因爲燈閃爍是經過設置矩形的背景顏色來實現的(固然我這裏還加了一個陰影,爲了有「亮燈」的效果),因此咱們對這個矩形的背景顏色屬性進行數據綁定,而後經過 data.a 方法獲取和設置屬性值。

{
    "type": "rect",//矩形
    "background": {//矩形背景
        "func": "attr@rectBg2",//數據綁定string類型若以attr@***開頭,則返回data.getAttr(***)值,其中***表明attr的屬性名
        "value": "rgb(255,0,0)"//屬性默認值
    },
    "shadow": true,//設置爲true顯示陰影
    "shadowColor": {//陰影顏色
        "func": "attr@shadowColor2",//數據綁定string類型
        "value": "rgba(255,0,0,0.35)"//屬性默認值
    },
    "shadowOffsetX": 0,//選中圖元的陰影水平偏移
    "shadowOffsetY": 0,//選中圖元的陰影垂直偏移
    "rect": [//組件繪製在矢量中的矩形邊界
        4.38544,//x 軸座標
        32.55505,//y 軸座標
        14.46481,//width
        6.1554//height
    ]
}
複製代碼

上面是我對矩形燈矢量的部分從新繪製後的代碼,看出什麼不一樣了?對,background 屬性和 shadowColor 屬性都出現了兩個值,而且這兩個值看起來「怪怪的」?數據綁定(http://hightopo.com/guide/guide/core/databinding/ht-databinding-guide.html)沒有那麼難,綁定的格式很簡單,只需將之前的參數值用一個帶 func 屬性的對象替換便可,若是對應的 func 取得的值爲 undefined 或 null 時,則會採用 value 屬性定義的默認值。

func 的內容有如下幾種類型:

  • function 類型,直接調用該函數,並傳入相關 Data 和 view 對象,由函數返回值決定參數值,即 func(data, view) 調用。
  • string 類型:
    • style@*** 開頭,則返回 data.getStyle(***) 值,其中 *** 表明 style 的屬性名。
    • attr@*** 開頭,則返回 data.getAttr(***) 值,其中 *** 表明 attr 的屬性名。
    • field@*** 開頭,則返回 data.*** 值,其中 *** 表明 data 的屬性名。
    • 若是不匹配以上狀況,則直接將 string 類型做爲 data 對象的函數名調用 data.***(view),返回值做爲參數值。

因此咱們經過 "func" 來綁定數據,這裏用的是 attr@*** 的方式綁定,到時候要調用這個屬性的時候就直接經過 data.getAttr(***) 或者縮寫 data.a(***) ;而後經過 "value" 設置一個默認值,做爲 func 返回的值爲空時的「備用」。

通常咱們將代碼比較多的矢量圖放在一個 json 文件中,我取名叫作 service3d.json 放在 scene 文件夾下 ,經過 ht.Default.xhrLoad 方法解析 json 文件的內容,以下:

ht.Default.xhrLoad('scene/service3d.json', function(text) {
    var json = ht.Default.parse(text);
    dm.deserialize(json);//反序列化
})
複製代碼

其中 deserialize 反序列化函數是將數據反序列化到模型,傳入的參數 json 爲數據信息對象,用於解析生成對應的 Data 對象並添加到數據容器中。

由於 xhrLoad 方法是異步加載,爲了不後面出現獲取不到數據的問題,咱們將剩下的節點屬性控制代碼也寫在 xhrLoad 函數中:

dm.each(function(data) {//遍歷dataModel
    var infos = [//我設置的業務屬性名稱
        {shadowColor: 'shadowColor1', background: 'rectBg1'},
        {shadowColor: 'shadowColor2', background: 'rectBg2'},
        {shadowColor: 'shadowColor3', background: 'rectBg3'},
        {shadowColor: 'shadowColor4', background: 'rectBg4'},
        {shadowColor: 'shadowColor5', background: 'rectBg5'},
    ];
    infos.forEach(function(info) {//遍歷infos數組
        data.a(info.shadowColor, 'rgba(255, 0, 0, 0.35)');//註冊業務屬性 attr 爲業務屬性 簡寫爲 a
        data.a(info.background, 'rgb(255, 0, 0)');
    });

    setInterval(function() {//設置動畫 動態變化閃爍燈的亮和滅的顯示
        var random = Math.ceil(Math.random() * 5);//獲取5之內一個隨機整數 (能夠配合我設置的業務屬性名稱)
        var shadowName = 'shadowColor' + random,
            bgName = 'rectBg' + random;

        if(data.a(shadowName) === 'rgba(255, 0, 0, 0.35)') {//若是是紅色透明
            data.a(shadowName, 'rgba(0, 255, 0, 0.35)');//設置爲綠色透明
        }
        else if(data.a(shadowName) === 'rgba(0, 255, 0, 0.35)') {//若是是綠色透明
            data.a(shadowName, 'rgba(255, 0, 0, 0.35)');//設置爲紅色透明
        }

        if(data.a(bgName) === 'rgb(255, 0, 0)') {//若是是紅色
            data.a(bgName, 'rgb(0, 255, 0)');//設置爲綠色
        }
        else if(data.a(bgName) === 'rgb(0, 255, 0)') {//若是是綠色
            data.a(bgName, 'rgb(255, 0, 0)');//設置爲紅色
        }
    }, 1000);
    
});
複製代碼

值得注意的一點是,雖然咱們在 json 中已經綁定了業務屬性(這裏是「shadowColor1,2,3,4,5...」和「rectBg1,2,3,4,5」),可是節點上並無這個屬性,因此咱們須要註冊一下這些屬性,並給這些屬性設置屬性值。

而後咱們就能夠經過調用這些屬性來動態更新 Data 上的屬性值圖形界面就會自動刷新,從而達到實時顯示數據的效果。由於 HT 只有一個數據模型,綁定 DataModel 的圖形組件並無組件內部的其餘數據模型,因此組件都是如實根據 DataModel 來呈現界面效果,所以當用戶拖拽圖元移動時, 本質也是修改了數據模型中 Node 的 position 位置值,而該屬性變化觸發的事件經過模型再次派發到圖形組件,引起圖形組件根據新的模型信息刷新界面。

總結

其實數據綁定沒有什麼很深奧的部分,HT 也不須要你考慮太多,一切以最簡單的方式進行着。這個 Demo 須要注意的就是,相同的圖片,若是要顯示不一樣,那麼確定須要建立不一樣的節點,如果節點相同,那麼變化確定相同的!

相關文章
相關標籤/搜索