基於HTML5快速搭建TP-LINK電信拓撲裝置皮膚

圖撲軟體發表於2017-05-18

  今天我們以真實的TP-LINK裝置皮膚為模型,完成裝置皮膚的搭建,和指示燈的閃爍和圖元流動。

  先來目睹下最終的實現效果:http://www.hightopo.com/demo/blog_tplink_20170511/index.html

 

 

1、TP-LINK皮膚

    我們從TP-LINK的裝置皮膚開始,裝置皮膚的示意圖如下:

               

    顯而易見,裝置皮膚基本上能由HT for Webhttp://www.hightopo.com/guide/guide/core/beginners/ht-beginners-guide.html)的基本圖形(rect、circle、oval等)構成,而中間的介面需要用自定義圖形來解決,下面讓我們一步步實現它,準備工作如下:

    匯入我們的HT(http://www.hightopo.com/):

<script src="ht.js"></script> 

     建立資料模型容器,並將其加入DOM:

dataModel = new ht.DataModel();//建立資料模型容器  
graphView = new ht.graph.GraphView(dataModel);//建立拓撲圖元件  
graphView.addToDOM();   

    可能有人看到這裡的addToDOM()很疑惑?沒錯,這是HT新增的API!之前我們要建立一個圖形介面,不光需要在CSS樣式中定義mian的top、left,還需要對window物件的resize事件進行監聽等等,所以我們新增addToDOM()幫您做好這一系列的事情,可以看看原始碼中的實現方式:

    p.addToDOM = function(){     
        var self = this,  
            view = self.getView(),     
            style = view.style;  
        document.body.appendChild(view);              
        style.left = '0';  
        style.right = '0';  
        style.top = '0';  
        style.bottom = '0';        
        window.addEventListener('resize', function () { self.iv(); }, false);  
        self.iv();  
    },  

     準備工作完成後,就可以開始皮膚的繪製,對於基本圖形,只需設定其相應地樣式即可,例如有立體效果的按鈕部分:

{  
      type: "circle",  
      shadow: true,  
      background: "rgb(0,0,0)",  
      borderWidth: 1,  
      borderColor: "rgb(0,0,0)",  
      border3d: true,  
      gradient: "spread.horizontal",  
      gradientColor: "rgb(79,77,77)",  
      dashColor: "rgb(0,0,0)",  
      rotation: 3.141592653589793,  
      rect: [  
        677, 157,  
        43, 34  
      ]  
} 

  

     對於自定義圖形,前面也有介紹過,詳見HT for Web形狀手冊http://www.hightopo.com/guide/guide/core/shape/ht-shape-guide.html)。需要制定向量型別為shape,其形狀主要由points和segments這兩個屬性描述:

     points為ht.List型別陣列的頂點資訊,頂點為{x: 100, y:200}格式的物件;

     segments為ht.List型別的線段陣列資訊,線段為1~5的整數,分別代表不同的頂點連線方式,segments主要用於繪製曲線,或者有跳躍斷點的情況,其1~5的取值含義如下:

     1:moveTo,佔用一個點的資訊,代表一個新路徑的起點;

     2:lineTo,佔用一個點資訊,代表從上次最後點連線到該點;

     3:quadraticCurveTo,佔用三個點資訊,第一個點作為曲線控制點,第二個點作為曲線結束點;

     4:bezierCurveTo,佔用三個點資訊,第一和第二個點作為曲線控制點,第三個點作為曲線結束點;

     5:closePath,不佔用點資訊,代表本次路徑繪製結束,並閉合到路徑的起始點。

         

     示例如下:

    ht.Default.setImage('tplink', {  
        width: 97,  
        height: 106,  
        comps: [  
            {  
          type: "shape",  
          background: "rgb(20,60,140)",  
          borderWidth: 8,  
          borderColor: "gray",  
          borderCap: "round",  
          points: [  
            269, 140,  
            359, 140,  
            359, 180,  
            329, 180,  
            329, 190,  
            299, 190,  
            299, 180,  
            269, 180,  
            269, 140  
          ]}  
        ]  
    });  

    將所有的圖形資料整合後,就形成我們的TPLINK皮膚的資料,整合方法如下:

    ht.Default.setImage('tplink', {  
        width: 97,  
        height: 106,  
        comps: [  
            {  
          type: "shape",  
          background: "rgb(20,60,140)",  
          borderWidth: 8,  
          borderColor: "gray",  
          borderCap: "round",  
          points: [  
            269, 140,  
            359, 140,  
            359, 180,  
            329, 180,  
            329, 190,  
            299, 190,  
            299, 180,  
            269, 180,  
            269, 140  
          ]},  
           {  
          type: "circle",  
          shadow: true,  
          background: "rgb(0,0,0)",  
          borderWidth: 1,  
          borderColor: "rgb(0,0,0)",  
          border3d: true,  
          gradient: "spread.horizontal",  
          gradientColor: "rgb(79,77,77)",  
          dashColor: "rgb(0,0,0)",  
          rotation: 3,  
          rect: [  
            677, 157,  
            43, 34  
          ]},  
          //...  
          //...  
          //...  
          //多個圖形元件  
      ]  
    });  

    這只是註冊圖片的其中一種方法,我們也可以直接通過url的方式進行註冊(詳情見HT for Web入門手冊): 

    ht.Default.setImage('tplink', 'symbols/TPLink.json');   

    將註冊的向量圖片名稱設定到模型上:

    var node = new ht.Node(),  
    node.setImage('tplink');  
    dataModel.add(node);  

    甚至在最新版的HT中,已經支援無需註冊,直接呼叫setImage(),傳入URL引數的方式(在我的Demo中就是使用的這種方法)。這種方法更加簡潔,但是如果許多場景都應用到同一圖片時,還是建議使用者通過註冊的圖片的,避免多次修改URL:

    node.setImage('symbols/TPLink.json');  

    好了,現在在瀏覽器中預覽你的HTML文件,是不是有個TPLINK皮膚?

    最後,怎麼讓我們的指示燈閃爍起來呢?用HT開發的產品,要實現閃爍效果很簡單,因為HT預定於圖形元件預設就已與DataModel中的Data資料繫結,繫結的格式也很簡單,只需將以前的引數值用一個帶func屬性的物件替換即可,詳見HT for Web資料繫結手冊http://www.hightopo.com/guide/guide/core/databinding/ht-databinding-guide.html)。在這裡指示燈的閃爍實際上是visible屬性值變化產生的結果,所以我們只需要給visible屬性資料繫結,如下所示:

    {  
          "type": "oval",  
          "visible": {  
            "func": "attr@visibility1"  
          },  
          "shadow": true,  
          "shadowColor": "rgba(208,240,2,0.35)",  
          "background": "rgb(178,184,141)",  
          "gradient": "radial.center",  
          "gradientColor": "rgb(247,255,0)",  
          "rect": [  
            79, 53,  
            31, 32  
          ]  
     },  

 

setInterval(function(){  
                    node.a('visibility1', !t_node.a('visibility1'));  
}, 400); 

    到這裡,你已經成功完成一個TPLINK皮膚的製作 (~ . ~),當然還剩伺服器的製作,這裡就不再贅述,複雜TPLINK皮膚都完成了,伺服器還遠嗎?

2、連線

  大家也有注意到,我們的Demo中有兩條連線,那連線應該怎麼做呢?

  HT預設提供的是直線和多點連線,但是在繪製流程圖、組織結構圖和思維導圖等應用還需要更多的連線型別,  詳情戳HT for Web連線型別手冊http://www.hightopo.com/guide/guide/plugin/edgetype/ht-edgetype-guide.html)。

  

  

  在我們的Demo中,兩條連線伺服器和TP-LINK的曲線,均是使用自定義的新連線型別。

  ht.Default.setEdgeType(type, func, mutual)函式可以用來自定義連線型別:

  其中:

        type:字串型別的連線型別,對應style的edge.type屬性;

    fuc:函式型別,根據傳入引數(edge, gap, graphView, sameSourceWithFirstEdge)返回走線的走向資訊;

                edge:當前連線物件;

                gap:多條連線成捆時,笨連線物件對應中心連線的間距;

                graphView:當前對應的拓撲元件物件;

                sameSourceWithFirstEdge:boolean型別,該連線是否與同組的同一條連線同源;

                返回值為{points:new ht.List(...),segments:new ht.List(...)}結構的連線走向資訊,segments的取值同上;

    mutual:該引數決定連線是否影響起始或者結束節點上的所有連線,預設為false代表隻影響同source和target的EdgeGroup中的連線。

  具體實現時,我們需要再引入:

    <script src='ht-edgetype.js'></script>  

  然後呼叫ht.Default.setEdgeType(type, func, mutual)函式,程式碼如下:

    ht.Default.setEdgeType('line', function(edge){  
                        var sourcePoint = edge.getSourceAgent().getPosition(),  
                            targetPoint = edge.getTargetAgent().getPosition(),  
                            points = new ht.List();         
                            points.add(sourcePoint);  
                            points.add({  
                                x: (sourcePoint.x + targetPoint.x)/2,   
                                y: (sourcePoint.y + targetPoint.y)/2 + 300  
                            });                    
                            points.add(targetPoint);                                                         
      
                        return {  
                            points: points,  
                            segments: new ht.List([1, 3])  
                        };                   
    });  

  建立一條新的連線時,注意這時候連線型別edge.type為我們自定義的連線型別‘line’:

    var edge = new ht.Edge();  
    edge.setSource(startNode);  
    edge.setTarget(endNode);  
    edge.setLayer('edgeLayer');  
    edge.s({  
           'edge.type': 'line',  
           'edge.color': '#0A3791',  
           'edge.width': 8,  
           'edge.center': true  
           });  
    dataModel.add(edge);  

  到這裡連線已經基本完成,還有一點,大家可能對setLayer()方法不是很熟悉,其實這個方法是用於設定連線和圖元的層級,因為預設的層級是edge在node之下,所以需要設定層級後,呼叫graphView的setLayers方法更改層級之間的關係: 

    graphView.setLayers(['nodeLayer', 'edgeLayer']);  

  若對自定義連線型別仍舊有疑問,可以戳例子http://www.hightopo.com/guide/guide/plugin/edgetype/examples/example_custom.html)加深瞭解。

3、流動

  先來看看HT產品中流動的炫酷效果(戳地址http://www.hightopo.com/guide/guide/plugin/flow/examples/example_demo1.html)可看詳情):

  

  在我的Demo中兩條連線應用了不同方式的流動,但是兩種方式需要ht.flow外掛。這個外掛在ht.Shape和ht.Edge型別上擴充套件了樣式控制流動效果,使用者可以通過ht.Shape.setStyle()和ht.Edge.setStyle()來操作這些樣式,下面簡單介紹幾種樣式:

    1、flow值為true和false,控制此ht.Shape和ht.Edge是否可流動,預設為false;

    2、flow.count,控制流動組的個數,預設為1;

    3、flow.step,控制流動的步進,預設為3;

    4、flow.element.image,字串型別,指定流動組元素的圖片,圖片須提前通過ht.Default.setImage()註冊;

     ....

   等等,還有很多的樣式任你玩,詳情戳地址http://www.hightopo.com/guide/guide/plugin/flow/ht-flow-guide.html);

   這裡必須要引入流動特效外掛:

<script src="js/ht-flow.js"></script>

  在這裡,我們先將流動的圖片提前註冊:

 ht.Default.setImage('arrow', 'symbols/arrow.json');  

  第一種方式中,直接在連線edge上設定流動相關的屬性(做完後別忘了呼叫啟動流動的API),在這裡通過設定flow.element.image屬性值為'arrow'的方式設定流動的圖片:

    edge.setStyle({  
        'edge.type': 'line',  
        'edge.color': '#0A3791',  
        'edge.width': 8,  
        'edge.center': true,  
        'flow': true,  
        'flow.element.image': 'arrow',  
        'flow.element.count': 1,   
        'flow.element.max': 30,                                                 
        'flow.element.autorotate': true                         
    });  
    raphView.enableFlow(40);//啟動流動;  

  重新整理頁面,arrow在edge上流動起來了!可能還有人會疑問“如果我的流動組元素不是圖片,是圖元呢?”,沒錯,這就是第二種方式!

  第二種方式,針對的是流動元素組是圖元的情況:

    var flowNode = new ht.Node();                   
    flowNode.setImage('arrow');  

  因為流動實際上是圖元的位置隨著時間發生了變化,所以,我們可以更改圖元的位置來控制它的流動,通過呼叫flow外掛現成的API- - -calculateLength計算出流動線的長度length,然後改變當前步進百分比currentPercentage,具體實現如下:

    graphView.validate();//重新整理;  
    var length = graphView.calculateLength(edge),//流動線長度;  
        step = 4, //步進單位畫素;  
        stepPercentage = step / length * 100, // 步進百分比;  
        currentPercentage = 0; //當前步進百分比;  
      
    setInterval(function(){  
        var pos = graphView.getPercentPosition(edge, currentPercentage);//第二個引數為百分比,範圍0到100;  
        flowNode.setPosition(pos.x, pos.y);//改變流動節點的位置;  
        currentPercentage += stepPercentage;  
        if (currentPercentage > 100) currentPercentage = 0;  
    }, 400);  

  做完這些之後,重新整理頁面,怎麼仍舊沒有流動效果?

  其實這裡有一個坑,那就是在計算length之前,必須先呼叫graphView.validate(),為什麼呢?為了提高效率,graphView並不是實時重新整理,而是多個圖元發生改變後統一重新整理,所以這裡的graphView.validate()的功能是進行重新整理graphView.

  最後,附上Demo的原始碼(http://www.hightopo.com/demo/blog_tplink_20170511/index.html),希望大家不吝賜教。

 

 

  

 

相關文章