基於 HTML5 Canvas 實現的 TP-LINK 電信拓撲裝置皮膚
前言
今天我們以真實的 TP-LINK 裝置皮膚為模型,完成裝置皮膚的搭建,和指示燈的閃爍和圖元流動。
先來目睹下最終的實現效果:http://www.hightopo.com/demo/blog_tplink_20170511/index.html
程式碼實現
TP-LINK皮膚
我們從 TP-LINK 的裝置皮膚開始,裝置皮膚的示意圖如下:
顯而易見,裝置皮膚基本上能由 HT for Web 的基本圖形(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 樣式中定義 main 的 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的取值含義如下:
- moveTo,佔用一個點的資訊,代表一個新路徑的起點;
- lineTo,佔用一個點資訊,代表從上次最後點連線到該點;
- quadraticCurveTo,佔用三個點資訊,第一個點作為曲線控制點,第二個點作為曲線結束點;
- bezierCurveTo,佔用三個點資訊,第一和第二個點作為曲線控制點,第三個點作為曲線結束點;
- 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 的方式進行註冊(詳情見 http://www.hightopo.com/guide/guide/core/beginners/ht-beginners-guide.html ):
ht.Default.setImage('tplink', 'symbols/TPLink.json');
將註冊的向量圖片名稱設定到模型上:
var node = new ht.Node(),
node.setImage('tplink');
dataModel.add(node);
甚至在最新版的 HT 中,已經支援無需註冊,直接呼叫 setImage(),傳入 URL 引數的方式。這種方法更加簡潔,但是如果許多場景都應用到同一圖片時,還是建議使用者通過註冊的圖片的,避免多次修改 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 皮膚都完成了,伺服器還遠嗎?
連線
大家也有注意到,我們的 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 屬性;
- func:函式型別,根據傳入引數 (edge, gap, graphView, sameSourceWithFirstEdge) 返回走線的走向資訊;
1). edge:當前連線物件;
2). gap:多條連線成捆時,笨連線物件對應中心連線的間距;
3). graphView:當前對應的拓撲元件物件;
4). 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 )加深瞭解。
流動
先來看看 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 ),希望大家不吝賜教。
相關文章
- 基於 HTML5 Canvas 電信網路拓撲圖的快速搭建HTMLCanvas
- 基於 HTML5 Canvas 的拓撲元件 ToolTip 應用HTMLCanvas元件
- 快速建立 HTML5 Canvas 電信網路拓撲圖HTMLCanvas
- 基於 Electron 實現 uTools 的超級皮膚
- 基於 HTML5 WebGL 的 3D 網路拓撲圖HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 網路拓撲圖WebHTML3D
- 基於 HTML5 Canvas 2D 拓撲圖和 3D 機櫃模型的增刪操作HTMLCanvas3D模型
- 基於 HTML5 Canvas 實現的文字動畫特效HTMLCanvas動畫特效
- 基於 HTML5 Canvas 的電信機櫃 U 位動態管理HTMLCanvas
- 基於 HTML5 Canvas 實現文字動畫特效HTMLCanvas動畫特效
- 基於 WebGL 的 HTML5 網路拓撲結構 3D 圖WebHTML3D
- 基於 HTML5 的網路拓撲圖之 DataBinding 資料繫結HTML
- DFS實現拓撲排序排序
- 基於 HTML5 網路拓撲圖的快速開發之入門篇(一)HTML
- 基於 HTML5 網路拓撲圖的快速開發之入門篇(二)HTML
- 基於 OpenLayers3 實現的 HTML5 GIS 電信資源管理系統S3HTML
- vue 實現動態拓撲圖Vue
- 圖的拓撲排序詳解與實現排序
- 基於 HTML5 OpenLayers3 實現 GIS 電信資源管理系統HTMLS3
- 基於d3.js的關係拓撲圖JS
- 圖解拓撲排序+程式碼實現圖解排序
- 基於 Canvas 的 HTML5 文字動畫特效CanvasHTML動畫特效
- 基於“SMemory”的部落格園皮膚美化
- 快速開發基於 HTML5 網路拓撲圖應用之 DataBinding 資料繫結篇HTML
- 基於 HTML5 Canvas 的元素週期表展示HTMLCanvas
- 基於 HTML5 Canvas 的樓宇自控系統HTMLCanvas
- 基於 HTML5 Canvas 的元素週期表的展示HTMLCanvas
- 基於 HTML5 Canvas 的可互動旋鈕元件HTMLCanvas元件
- 基於HTML5 WebGL 將拓撲圖和圖表繪製在 3D 六面體上HTMLWeb3D
- 基於 canvas 的市場交易深度圖 JS 實現CanvasJS
- Noc拓撲
- 拓撲排序排序
- 基於 HTML5 實現的風電、光伏新能源管理系統HTML
- 使用 HTML5 Canvas 實現簽名功能HTMLCanvas
- Java實現管線拓撲關係連通性分析Java
- App 多區域皮膚(主題)的實現APP
- 摺疊皮膚元件的設計與實現元件
- 寶塔Windows皮膚的安裝Windows