视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
快速搭建TP-LINK电信拓扑设备面板基于HTML5的实现方法
2020-11-27 15:08:58 责编:小采
文档
   今天我们以真实的TP-LINK设备面板为模型,完成设备面板的搭建,和指示灯的闪烁和图元流动。


1、TP-LINK面板

我们从TP-LINK的设备面板开始,设备面板的示意图如下:

显而易见,设备面板基本上能由HT for Web(本图形(rect、circle、oval等)构成,而中间的接口需要用自定义图形来解决,下面让我们一步步实现它,准备工作如下:

导入我们的HT

<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.1415926535793, 
 rect: [ 
 677, 157, 
 43, 34 
 ] 
}

对于自定义图形,前面也有介绍过,详见HT for Web形状手册。需要制定矢量类型为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数据绑定手册。在这里指示灯的闪烁实际上是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连线类型手册

  

  在我们的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']);

  若对自定义连线类型仍旧有疑问,加深了解。

3、流动

  先来看看HT产品中流动的炫酷效果情:

  

  在我的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()注册;

  ....

  等等,还有很多的样式任你玩,

   这里必须要引入流动特效插件:

<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.

下载本文
显示全文
专题