点击添加基于HTML5Canvas的2D3D柜体模型
时间:2023-04-05 15:15:03
HTML5
今天回过头来消化我们的数据容器DataModel。这里给出一个典型的数据模型事件处理示例,供新手参考。这个例子看起来很简单,其实结合了数据模型中三个非常重要的事件处理部分:属性变化事件监听、选择变化事件监听和数据模型变化事件监听。为了让这个例子更真实,我对这个简单的例子做了一些改动,下面我会一一说明。示例地址:http://hightopo.com/guide/gui...这是我改造后的样子。dataModel数据容器是共享的,通过监听数据容器的增删事件得到当前结果,在显示器上显示做了一点“手脚”。让我们从头分析这个例子,你就会知道为什么我会提出这个简单的例子。首先,我们必须创建一个将用作基础的场景。整个场景分为三个部分,顶部工具栏、2D部分和3D部分。顶部工具栏部分用纯HTML编写:AddRemove清除因为有点击事件,所以我们直接在button按钮上执行,后面的span标签显示的是纯文本内容。我们知道HT的所有组件都是基于一个根div。把这个div部署在一个html页面上很简单,但是HT内部给这个div设置了绝对定位,所以我们在把这个div添加到一个HTML页面的时候,也是在绝对定位中设置position,我在页面中添加了一个div,并将HT部分添加到此div:
dataModel=newht.DataModel();g3d=newht.graph3d.Graph3dView(dataModel);g3d.setGridVisible(true);//设置网格可见g3d.setEye(185,50,470);//设置3d的眼睛位置g3d.setCenter(200),47,10);//设置3d的中心位置,这两个属性是为了用户在3d上看场景更舒服,更直接g2d=newht.graph.GraphView(dataModel);g2d.setEditable(true);//设置二维图元可编辑g2d.fitContent(true);//显示页面上所有图元splitView=newht.widget.SplitView(g2d,g3d,'v',0.3);//拆分组件,安装2d和3d场景splitView.addToDOM();//将拆分组件添加到body,并设置绝对定位位置myDiv=document.getElementById('myDiv');myDiv.appendChild(splitView.getView());//将拆分组件添加到myDiv中,然后将节点添加到dataModel数据模型中。我们这里做的是机房机柜,本来想做服务器的,手头上暂时只有这个资源,还不错。我封装了一个add函数,一个delete函数,一个clear函数,分别对应工具栏上的“Add”,“Remove”,“Clear”三个函数:functionaddData(){vardata=newht.Node();data.setPosition(index*60,50);data.setName('节点'+索引);data.setSize(40,40);data.setImage('内阁');data.s({'image.stretch':'centerUniform','shape3d':'cabinet'});索引++;dataModel.add(数据);返回数据;}functionremoveData(){if(!dataModel.sm().ld())return;dataModel.remove(dataModel.sm().ld());}functionclearDataModel(){dataModel.clear();index=0;}其中代码中出现的“data.setImage('cabinet')”,我是通过ht.Default.setImage('cabinet','imageURL')定义的,调用的时候直接调用data.setImage('图像名称')。详见HTforWeb入门手册图片章节。2D图片的显示和3D模型的显示肯定是不一样的。在2D中,我们可以直接使用贴图来解决问题。HT3D支持obj格式的模型展示。这是部分:HT封装了解析obj格式的函数ht。Default.loadObj函数用于导入模型。这个函数有三个参数。第一个和第二个是obj文件的路径和mtl文件的路径。第三个参数是json格式控制参数。具体参数请参考HTforWebOBJ手册LoadObj函数章节(ps:使用obj模型会导致跨域问题,应该在服务端运行):ht.Default.loadObj('obj/cabinet组件1.obj','obj/cabinetcomponent1.mtl',{cube:true,//是否将模型缩放到单元1的尺寸范围,默认为falsecenter:true,//模型是否居中prefix:'obj/',//路径前缀,如果路径前缀写在前面的参数中,这个也可以留空shape3d:'cabinet',//指定shape3d名称finishFunc:function(modelMap,array,rawS3){//调用ht.Default.parseObj返回解析后的值,如果加载或解析失败,返回值为Emptywindow.rawS3=rawS3;//让当前模型的大小为原始大小if(modelMap){cabinet1=addData();//添加两个节点到dataModelcabinet2=addData();}}});现在,节点和模型已经导入到场景中,终于来到我们今天的重点,事件交互部分。ht.DataModel数据容器管理Data数据的增删改查和事件分发。这里我们管理这两个事件的Data数据。addDataModelChangeListener(function(e){},scope)添加数据模型增删改事件监听器,可以简写为mm(func,scope),func是监听函数,scope是监听函数域(可选),监听函数中的事件有两个属性:kind和data,其中kind是事件的类型:e.kind==='add'表示添加一个Data对象,e.data是添加的对象e.kind==='remove'表示删除Data对象,e.data为要删除的对象e.kind==='clear'表示容器清空这里我们将模型的增删改事件的监听结果传过去到html中id为model的span作为内容:varmodel=document.getElementById('model');dataModel.addDataModelChangeListener(function(e){if(e.kind==='add')//If事件类型为add,addnodemodel.innerHTML=e.data+'added';//用添加的节点added替换model的内容if(e.kind==='remove')model.innerHTML=e.data+'删除';if(e.kind==='clear')model.innerHTML='dataModelcleared'});addDataPropertyChangeListener(function(e){},scope)在模型中添加数据属性变化事件监听,可以简写为md(func,scope),其中event事件有四种类型的属性:e.data表示属性变化的对象e.property表示属性变化的名称e.newValue表示属性的新值e.oldValue表示属性Data对象的旧值调用firePropertyChange(property,oldValue,newValue)触发属性变化事件:获取/设置类型属性,如setAge(98)触发事件的e.property在agestyle类型的属性名前加上s:前缀,如setStyle('age',98),触发事件的e.property为s:ageattr类型属性名,以a:为前缀来区分,比如setAttr('age',98)触发的事件的e.property是a:age这里我们将model中Data的属性变化事件的监听结果传递给spanwithHTML中的id属性作为内容:varmodel=document.getElementById('model');dataModel.addDataPropertyChangeListener(function(e){property.innerHTML=e.data+'\'s'+e.property+'已经改变,旧值为'+e.oldValue+'和新值是'+e.newValue;});最后我们在selected节点上添加监听器,监听selectedchange事件ht.SelectionModel管理DataModel模型中Data对象的选择状态,每个DataModel对象内置了一个SelectionModel选择模型,并控制SelectionModel控制绑定DataModel的所有组件的对象选择状态,即共享同一个DataModel的组件默认具有选中的联动功能。如果你希望某些组件不与其他组件链接,你可以调用view.setSelectionModelShared(false),这样视图就会创建一个专用的SelectionModel实例。综上所述,获取SelectionModel有两种方式:dataModel.getSelectionModel()获取数据容器中组件共享的选中模型。view.getSelectionModel()获取当前组件使用的选定模型。当selectionModelShared为false时,它??返回视图特定的选择模型。addSelectionChangeListener(function(e){},scope)添加一个监听器来监听selectedchange事件,简写为ms(func,scope):e.datas包含所有selected状态改变的对象,之前被选中现在未被选中,或者之前没有selected现在选中的对象e.kind==='set'表示这个事件是由setSelection(datas)引起的e.kind==='remove'表示这个事件是由removeSelection(datas)引起的e.kind==='append'表示这个事件是由appendSelection(datas)触发的e.kind==='clear'表示这个事件是由clearSelection(datas)触发的这里我们会传递model中Data的selectedchange事件的监听结果以选择跨度的HTML中的id作为内容:=0)selection.innerHTML='Nothingselected';//如果选中模型的“长度”为0,即没有选中内容elseif(dataModel.sm().size()===1)selection.innerHTML=e.datas+'选中';elseselection.innerHTML=dataModel.sm().size()+'选择的数据';});以上,所有的代码都分析完了!您可以创建自己的3D模型!