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

基于HTML5WebGL的3D网络拓扑图

时间:2023-04-05 20:06:37 HTML5

如今,3D模型已经被应用于各个领域。它们在医疗行业用于制作精确的器官模型;电影业将它们用于移动角色、物体和逼真的电影;视频游戏行业将它们用作计算机和视频游戏的资源;科学领域将它们用作化合物的精确模型;建筑行业使用它们来展示拟建的建筑或景观图;工程界使用它们来设计新设备、车辆、结构和其他应用程序;并且3D模型通常是动画的,例如,3D模型广泛用于故事片、计算机和视频游戏中。它们可以在3D建模工具中使用,也可以单独使用。为了方便地形成动画,通常会在模型中添加一些额外的数据。例如,一些人或动物的3D模型具有完整的骨骼系统,这样运动看起来更逼真,并且可以通过关节和骨骼来控制运动。这些都让我们前端开发者觉得,如果不用学习unity3d或者其他游戏开发工具也能实现3D效果,并且能够通过代码准确控制移动或者方向,那该多好啊。..所以我使用HTForWeb中的3D组件实现了一个小例子。HT中3D组件的大部分功能我都用过了。我制作这个例子是为了掌握3D组件并尝试将它们放入示例中。有需要的可以参考。先来看看整体实现效果图:使用HTforWeb,用现有的3d模板制作三层底板不成问题。问题是如何把“电脑”和“机柜组件”放到图中的第一层?我从网上下载了obj格式的文件,然后使用HT中的ht.Default.loadObj(objUrl,mtlUrl,params)函数将模型加载进去。params部分可以参考http://www.hightopo。com/guide...,代码如下:ht.Default.loadObj('obj/cabinetcomponent1.obj','obj/cabinetcomponent1.mtl',{//loadobjfilecube:true,//是否将模型缩放到单元1的尺寸范围,默认为falsecenter:true,//模型是否居中,默认为false,设置为true会移动模型位置,使其内容为centeredshape3d:'box',//如果指定了shape3d名称,则HT会自动将所有材质模型加载解析后构建成一个数组,并以此名称注册finishFunc:function(modelMap,array,rawS3){//用于加载后回调处理 if(modelMap){  device2=createNode('box',floor1);//在一楼“floor”创建节点    device2.p3([x1-120,y1+13,z1+60]);//设置节点坐标    device2.s3(rawS3);//设置节点大小    createEdge(device1,device2);//创建连接    device3=createNode('box',floor1);    device3.s3(rawS3);    device3.p3([x1+120,y1+13,z1+60]);    createEdge(设备1,设备3); }}});finishiFunc函数中的三个参数定义如下:modelMap:调用ht.Default.parseObj求解解析后的返回值,如果加载或解析失败,则返回值为空array:所有材质模型的数组rawS3:包含所有模型的原始大小一般情况下,在实际应用中,我们会设置图元的大小到模型的原始大小在“计算机”上方有一个红色的可以旋转的三维“警告”,它依赖于ht.Default.setShape3dModel函数(HTforWebModelingManualhttp://www.hightopo.com/guide...3d模型,在ht中封装了很多建模函数,比较基础的有球体,圆柱体,立方体等,这里我使用createRingModel构造环的方法生成最外层的环“warning”。感叹号的上半部分是用createSmoothSphereModel构造的球体,感叹号的下半部分是createSmoothCylinderModel构造的圆柱体。我一开始直接用了封装在3D模型中的函数,所以我不知道函数中使用的参数是干什么用的,也不明白3D模型是怎么组成的,然后重新看了之前的《模型基础》,才知道原来3D模型是用一个曲面,最基本的是三角形曲面,复杂的曲面也是由多个三角形曲面组成。成型,然后绕特定轴旋转后成型。当然,这个轴由你决定。不同的轴可以生成不同的形状。颜色等样式设置请参考HTforWebStyleManual(http://www.hightopo.com/guide...。至于如何旋转3D模型,ht封装了addScheduleTask(Task)方法,以及我在Task的第三层调用了ht封装的一个旋转函数setRotation来设置旋转的顺序和方向,指定旋转的对象。下面是自定义“闹钟”3D模型的方法(注意:因为本例中的模型是自定义组合,如果要设置整体模型的颜色,需要使用“all.blend”样式属性):functioncreateAlarm(device,formPane){varringModel=ht.Default.createRingModel([8,1,10,1,10,-1,8,-1,8,1],null,null,false,false,100);//根据xy平面的曲线,绕一圈形成3D模型。varsphereModel=ht.Default.createSmoothSphereModel(8,8,0,Math.PI*2,0,Math.PI,2);//建立一个光滑的球体模型varcylinderModel=ht.Default.createSmoothCylinderModel(8,true,true,1,2,0,Math.PI*2,8);//构建光滑圆柱体模型varalarmArr=[//组合模型由三个模型ringModel,sphereModel,cylinderModel组成{shape3d:ringModel,//定义模型类型r3:[Math.PI/2,0,0],//设置旋转角度color:{//设置模型颜色func:'style@all.blend',//allinthedatabindingstylestyle.blend属性,可以通过data.s()获取和设置}},{shape3d:sphereModel,t3:[0,4,0],color:{func:'style@all.blend',}},{shape3d:cylinderModel,t3:[0,-3,0],color:{func:'style@all.blend',}}];ht.Default.setShape3dModel('alarm',{//注册自定义3D模型shape3d:alarmArr});varalarmTip=createNode('alarm',device);//创建一个shape3d为alarm的节点alarmTip.s3([2,2,2]);//设置节点大小alarmTip.p3(device.p3()[0],device.p3()[1]+60,device.p3()[2]);alarmTip.s('all.blend','red');//改变这个属性可以改变模型的颜色,因为返回的alarmTip在创建模型的时候已经被数据绑定了;}接下来我们看看如何让“报警”节点“闪烁”,我直接将这个动画绑定到节点上,这样可以直接通过节点控制动画所以我们在上面创建报警模型的时候,可以直接给节点绑定动画:if(formPane){alarmNode.scaleFunc=function(){//设置大小变化动画varsize=alarmNode.s3();//获取节点的大小if(size[0]===2&&size[1]===2&&size[2]===2)alarmNode.s3([1,1,1]);elsealarmNode.s3([2,2,2]);alarmNode.scaleTimer=setTimeout(alarmNode.scaleFunc,formPane.v('scaleInterval'));//设置动画}alarmNode.blinkFunc=function(){//设置闪烁动画varcolor=alarmNode.s('all.blend');//获取节点的样式if(color==='red')alarmNode.s({'all.blend':'yellow'});//如果节点的颜色为红色,则设置它变黄elsealarmNode.s({'all.blend':'red'});alarmNode.blinkTimer=setTimeout(alarmNode.blinkFunc,formPane.v('blinkInterval'));}alarmNode.rotateFunc=function(){//设置旋转动画alarmNode.setRotation(alarmNode.getRotation()+Math.PI/20);//获取节点当前旋转角度,在上面加上Math.PI/20角度这个旋转角度alarmNode.rotateTimer=setTimeout(alarmNode.rotateFunc,formPane.v('rotInterval'));}}上面的动画,我在formpanel上设置了属性来控制节点闪烁的速度,还有节点闪烁的动画等等,主要说一下这个功能在form表单上的实现:formPane。addRow([//在表单面板中添加一行元素{checkBox:{//checkboxlabel:'EnableBlink',//选中的复选框对应的文本内容:true,//设置选中的复选框onValueChanged:function(){//复选框值变化时的回调函数vardata=dataModel.getDataByTag('colorAlarm');//通过标签获取节点if(this.getValue()){//获取复选框的当前值true/falsedata.blinkTimer=setTimeout(data.blinkFunc,formPane.v('blinkInterval'));//通过设置节点的blinkTimer直接设置动画}else{clearTimeout(data.blinkTimer);//清除动画}}}},{id:'blinkInterval',//form可以通过getValue(简称v)获取此项的值slider:{//设置该属性后,HT会自动根据属性值构建ht.widget.Slider对象,保存在元素属性上min:0,//slider最小值max:1000,//slider最大step:50,//slider步长值:500,//滑块的当前值}}],[0.1,0.1]);//把这一行的两个item元素的width的值都设置为小于1。最后说一下小球在3D管道上流动的部分。这个功能真的很好用,效果也很好。分享给大家~,创建一条连接起始节点和结束节点的连接线,并设置这条连接线的样式,使用ht.线条会随着节点的位置而变化,非常方便:varpolyline=newht.Edge(source,target);//创建连接dataModel.add(polyline);//将连接添加到数据容器中polyline.s({'edge.width':5,//连接的宽度'edge.type':'points',//当连接类型为points时,连接的方向将由边决定.points属性,用于绘制折线'edge.points':[//Arrayofpointobjectsin{x:100,y:100}formatthatcanbesettoht.List,workswhenedge.typeispoints{x:source.getPosition3d()[0]+200,y:source.getPosition3d()[2],e:source.getPosition3d()[1]},{x:target.getPosition3d()[0]+400,y:target.getPosition3d()[2],e:target.getPosition3d()[1]}],'edge.segments':[1,4],//用于描述点连接样式,数组element是一个整数值'shape3d':'cylinder',//圆柱'shape3d.color':'rgba(242,200,40,0.4)','shape3d.resolution':30,//微柱数segments可以决定曲线的平滑度'edge.source.t3':[20,0,0],//连接源端的偏移量,[tx,ty,tz]格式,默认为空'edge.target.t3':[20,0,0]//连接目标端的偏移量,[tx,ty,tz]格式,默认为空});因为我们在创建连接时设置的点只是曲线上的两个点,所以如果我们要得到曲线当前形成的点,我们缺少源点和目标点。我们重新设置一个数组,将这两个点相加进去,后面会用到获取曲线上的所有点:varlist=newht.List();list.push({x:source.getPosition3d()[0],y:source.getPosition3d()[2],e:source.getPosition3d()[1]});//添加源点polyline.s('edge.points').each(function(item){//给数组添加style属性已经设置的两个点list.push(item);});list.push({x:target.getPosition3d()[0],y:target.getPosition3d()[2],e:target.getPosition3d()[1]});//添加目标点并创建球在管道上滑动的节点。这只是为了设置节点。实际添加到数据容器dataModel中时,需要在设置小球坐标后添加。如果没有给定节点,则通过设置节点的位置将节点添加到数据容器中。节点的初始位置是3D场景的中心[0,0,0]的位置小球滑动的动画代码如下:varball=newht.Node();//创建小球节点ball.s({//设置小球节点的样式'shape3d':'sphere',//设置小球3d模型为球形'shape3d.color':'rgba(40,90,240,0.4)'//设置3d模型的颜色});变量增量=10,标志=0;setInterval(function(){flag++;varlength=(polyline.a('total')||0)%polyline.a('length')+delta;//小球当前曲线长度varcache=ht.Default.getLineCacheInfo(list,polyline.s('edge.segments'));//获取曲线上点的信息varlineLength=ht.Default.getLineLength(cache);//获取曲线的总长度polyline.a('length',lineLength-50);//因为我设置了边的t3(相当于2d中的offset),所以线段的长度其实没有那么长varoffset=ht.Default.getLineOffset(cache,length);//曲线根据曲线上点的信息偏移ball.setPosition3d(offset.point.x+10,offset.point.y,offset.point.z);//设置节点的坐标polyline.a('total',length);if(flag===1)dataModel.add(ball);//此时节点已经有了坐标,可以添加到数据容器},10);我们还可以看到第二层有两个特殊的多边形“平行四边形”和“梯形”,平行四边形依赖于createParallelogramModel模型函数,这个函数比较简单,createExtrusionModel(array,segments,top,bottom,resolution,repeatUVLength,tall,elevation),array就是你要组成的图形的坐标点,这里只针对xz轴上绘制的平面图形,segments指的是这些坐标点如何连接,可以参考HTforWebShapeManual(http://hightopo.com/guide/gui...),top和bottom允许你选择是否有顶部或底部,以及分辨率微分段的数量。我们在画曲线的时候,可能只需要确定个别的几个点,然后在每两点的连线上把它分成多条线段,这样线段就会变得平滑。ht封装了这个参数,方便用户操作这些线段。repeatUVLength默认为空,设置该值顶部和底部纹理将按照指定的长度值重复。tall模型的高度默认为5。高程模型中心的y轴位置默认为0。设置这个值可以让xz上的平面绕y轴旋转。底层的环的效果是通过算法实现的。环要先确认环上有多少个元素,然后计算每两个之间的夹角,通过sin和cos计算出每个元素的位置,得到添加如下代码:names=['Device2','设备3','设备4','设备5','设备6','设备7','设备8','设备9'];名字。forEach(function(name,index){x=400,y=200,angle=45,r=120;x=x3+Math.sin((2*Math.PI/360)*angle*index)*r;y=z3+Math.cos((2*Math.PI/360)*angle*index)*r;device=createRect([x,y3+15,y],[w*0.1,15,h*0.1],'','',floor3);createEdge(device5,device);});如果还有不明白的部分,可以到官网(http://hightopo.com)查看相应的...,或者私信。附上这篇文章的例子:http://www.hightopo.com/demo/...