当前位置: 首页 > Web前端 > HTML5

基于HTML5Canvas的TP-LINK电信拓扑设备面板

时间:2023-04-05 00:13:33 HTML5

前言今天我们以真实的TP-LINK设备面板为模型,完成设备面板的搭建,指示灯的闪烁和图形元素的流动。先来看看最终的实现效果:http://www.hightopo.com/demo/...TP-LINK面板实现代码我们从TP-LINK设备面板说起。设备面板示意图如下:显然,设备面板基本上可以由HTforWeb的基本图形(矩形、圆形、椭圆等)组成,中间的界面需要用自定义图形解决。让我们一步一步地实施它。准备工作如下:导入我们的HT(http://www.hightopo.com/):创建一个数据模型容器并添加到DOM中:dataModel=新的ht.DataModel();//创建数据模型ContainergraphView=newht.graph.GraphView(dataModel);//创建拓扑图组件graphView.addToDOM();看到这里有些人可能会疑惑addToDOM()?没错,这是HT新增的API!之前我们要创建一个图形界面,不仅需要在CSS样式中定义main的top和left,还需要监听window对象的resize事件等,所以我们添加了addToDOM()帮你做这一系列的事情,你可以看看源码中的实现:p.addToDOM=function(){varself=this,view=self.getView(),style=view.style;document.body.appendChild(视图);style.left='0';style.right='0';style.top='0';style.bottom='0';window.addEventListener('resize',function(){self.iv();},false);f.iv();},准备工作完成后,就可以开始面板的绘制了。对于基本的图形,只需要设置相应的样式即可,比如有立体效果的按钮部分:{type:"circle",shadow:true,background:"rgb(0,0,0)",borderWidth:1、borderColor:"rgb(0,0,0)",border3d:true,gradient:"spread.horizo??ntal",gradientColor:"rgb(79,77,77)",dashColor:"rgb(0,0,0)",rotation:3.141592653589793,rect:[677,157,43,34]}自定义图形,之前介绍过,详见HTWeb的形状手册(http://www.hightopo.com/guide...)需要指定vector类型为shape,其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:“灰色”,borderCap:“圆形”,点:[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,渐变:“spread.horizo??ntal”,gradientColor:“rgb(79,77,77)”,dashColor:“rgb(0,0,0)”,rotation:3,rect:[677,157,43,34]},//...//...//...//多个图形组件]});这只是其中一张已注册的图片我们也可以直接通过url注册(详见http://www.hightopo.com/guide...): ht.Default.setImage('tplink','符号/TPLink.json');将注册的矢量图名设置为模型:varnode=newht.Node(),node.setImage('tplink');dataModel.add(节点);甚至在HT的最新版本中,已经支持直接调用setImage(),无需注册传入URL参数的方法这种方法比较简洁,但是如果很多场景应用到同一张图片,建议用户使用注册的图片,避免多次修改url:node.setImage('symbols/TPLink.json');好的,现在在浏览器中预览您的HTML文档中,是否有TPLINK面板?最后,我们如何让灯闪烁?使用HT开发的产品,实现闪烁效果是非常容易的,因为HT默认是调度绑定到DataModel中的Data数据的,绑定的格式也很简单,使用前面的参数即可value可以用一个func属性的对象来替换,详见HTforWebDataBindingManual(http://www.hightopo.com/guide...)。这里指示灯的闪烁其实是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面板的制作(~.~),当然还有服务器的制作,这里不再赘述。远吗?大家也注意到我们的demo中有两个connection,那么应该怎么connection呢?HT默认提供直线和多点连接,但在绘制流程图、组织结构图、思维导图等应用中需要更多的连接类型。详情请点击HTforWebConnectionTypeManual(http://www.hightopo.com/guide...)。在我们的Demo中,连接服务器和TP-LINK的两条曲线都使用了新的自定义连接类型。ht.Default.setEdgeType(type,func,mutual)函数可以自定义边类型:其中: type:字符串类型的边类型,对应样式的edge.type属性;func:函数类型,根据传入的参数(edge,gap,graphView,sameSourceWithFirstEdge)返回直线的方向信息;1).edge:当前线对象;2).gap:多条线捆绑时,笨线对象对应中心线3)。graphView:当前对应的拓扑组件对象;4).sameSourceWithFirstEdge:boolean类型,connection是否与同组的同一个connection同源;返回值为{points:newht.List(...),segments:newht.List(...)}结构的连接方向信息,segments的值同上;mutual:该参数决定连接是否影响起始节点或结束节点上的所有连接,默认如果为false,则只影响同源和目标的EdgeGroup中的连接。具体实现需要引入:然后调用ht.Default.setEdgeType(type,func,mutual)函数,代码如下:ht.Default.setEdgeType('line',function(edge){varsourcePoint=edge.getSourceAgent().getPosition(),targetPoint=edge.getTargetAgent().getPosition(),points=newht.List();点。add(sourcePoint);points.add({x:(sourcePoint.x+targetPoint.x)/2,y:(sourcePoint.y+targetPoint.y)/2+300});points.add(targetPoint);return{points:points,segments:newht.List([1,3])};});创建新行时,请注意行类型edge.type是我们自定义的行类型'line':varedge=newht.Edge();edge.setSource(startNode);edge.setTarget(endNode);edge.setLayer('edgeLayer');边缘.s({'edge.type':'line','edge.color':'#0A3791','edge.width':8,'edge.center':true});dataModel.add(边缘);到这里已经基本完成连接了。还有一点,大家可能对setLayer()方法不是很熟悉。其实这个方法是用来设置connection和primitives的层级的,因为默认层级是边在node下,所以需要设置层之后,调用graphView的setLayers方法改变层之间的关系: graphView.setLayers(['nodeLayer','edgeLayer']);如果对自定义连接类型还有疑惑,可以戳例子(http://www.hightopo.com/guide...)products,点击地址(http://www.hightopo.com/guide...)查看详情:在我的Demo中,两种连接使用不同的流方式,但是两种方式都需要ht.flow插件。此插件扩展了ht.Shape和ht.Edge类型的样式控制流效果。用户可以通过ht.Shape.setStyle()和ht.Edge.setStyle()来操作这些样式。这里有几个样式:  1、流值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...);这里必须介绍一下流光特效插件:在这里,我们先预先注册流光图:ht.Default.setImage('arrow','符号/arrow.json');首先在第一种方法中,直接在connection的边缘设置流相关的属性(完成后别忘了调用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);//启动流刷新页面,箭头在边上流动!可能还有人会问,“如果我的流元素组不是图片,而是图元呢?对,这就是第二种方法!第二种方法是针对流元素组是图元的情况:varflowNode=newht.Node();flowNode.setImage('arrow');因为流其实就是图元的位置随时间变化的,所以我们可以通过改变图元的位置来控制它的流,通过调用flow这个现成的插件API---calculateLength计算流线长度,然后改变当前步长百分比currentPercentage,具体实现如下:graphView.validate();//refreshvarlength=graphView.calculateLength(edge),//流线长度step=4,//步长单位像素stepPercentage=step/length*100,//步长百分比currentPercentage=0;//当前步长百分比setInterval(function(){varpos=graphView.getPercentPosition(edge,currentPercentage);//第二个参数是一个百分比,范围从0到100flowNode.setPosition(pos.x,pos.y);//改变流节点的位置currentPercentage+=stepPercentage;如果(currentPercentage>100)currentPercentage=0;},400);做完之后刷新页面,为什么还是没有流量效果?其实这里有个坑,就是在计算长度之前,graphView.validate()必须先调用,为什么?为了提高效率,graphView不是实时刷新的,而是多个图元素变化后统一刷新,所以这里的graphView.validate()的作用是刷新graphView。最后附上Demo源码(http://www.hightopo.com/demo/...),希望大家多多指教。