博客專欄

EEPW首頁 > 博客 > HTML5Canvas的3D壓力器反序列化詳解

HTML5Canvas的3D壓力器反序列化詳解

發(fā)布人:扣丁學(xué)堂 時(shí)間:2020-06-30 來源:工程師 發(fā)布文章

在現(xiàn)如今實(shí)際應(yīng)用中,我覺得能夠通過操作JSON文件來操作3D上的場景變化是非常方便的一件事,尤其是在做編輯器進(jìn)行拖拽圖元并且在圖元上產(chǎn)生的一系列變化的時(shí)候,都能將數(shù)據(jù)很直觀地反應(yīng)給我們,這邊我們簡單地做了個(gè)HTML5視頻教程基礎(chǔ)的例子,給大家參考看看。

333.png

  

實(shí)踐場景再現(xiàn):首先我們搭建一下這個(gè)例子的場景,熟悉的朋友可能已經(jīng)看出來了,這個(gè)場景分為三個(gè)部分:左、右上以及右下。HT通過ht.widget.SplitView可以很輕松地將場景分割,實(shí)現(xiàn)良好的頁面布局,最后將這個(gè)分割組件添加進(jìn)html的body體中,  

//場景搭建  

dataModel=newht.DataModel();//數(shù)據(jù)容器  

g3d=newht.graph3d.Graph3dView(dataModel);//3D組件  

propertyView=newht.widget.PropertyView(dataModel);//屬性組件  

formPane=newht.widget.FormPane();//表單組件  

rightSplit=newht.widget.SplitView(propertyView,formPane,'v',100);//分割組件  

newht.widget.SplitView(g3d,rightSplit,'h',0.65).addToDOM();  

接下來就是向場景中添加圖元,并把圖元添加到3D場景中,這時(shí)我們可以向圖元中添加各種屬性和樣式以及標(biāo)簽作為標(biāo)記,本例中用到的圖元是3D模型,利用ht.Default.parseObj函數(shù)對(duì)obj和mtl文件進(jìn)行解析:  

//添加模型  

varparams={center:true};//JSON格式控制參數(shù)傳入ht.Default.parseObj函數(shù)中  

varmodelMap=ht.Default.parseObj(meter_obj,meter_mtl,params);//解析obj和mtl文件,解析后返回的map結(jié)構(gòu)json對(duì)象中,每個(gè)材質(zhì)名對(duì)應(yīng)一個(gè)模型信息  

當(dāng)然,前提是要已經(jīng)聲明了meter_obj以及meter_mtl兩個(gè)文件,這里我們是將這兩個(gè)部分分別放到j(luò)s文件中,并在頭部調(diào)用。  

從上面的動(dòng)圖中我們可以看到,這個(gè)例子中需要變化的模型部分只有“指針”以及下面的“開關(guān)”兩個(gè)部分,所以我們通過遍歷的方式獲取這兩個(gè)obj模型的部分,并注冊3D模型:  

vararray=[];  

for(varnameinmodelMap){  

varmodel=modelMap[name];//modelMap中的模型  

array.push(model);  

if(name==='pointer'){//obj文件中的一個(gè)模型名稱為pointer  

model.mat={//矩陣變化參數(shù),可對(duì)模型進(jìn)行矩陣變化后導(dǎo)入  

func:function(data){  

varstart=Math.PI*0.736,  

range=Math.PI*1.49,  

angle=start-range*data.a('meter.value')/4;//動(dòng)態(tài)獲取了meter.value的值  

returnht.Default.createMatrix([//將一組JSON描述的縮放、移動(dòng)和旋轉(zhuǎn)等操作轉(zhuǎn)換成對(duì)應(yīng)的變化矩陣  

{t3:[0,-82.5,0]},  

{r3:[0,0,angle]},  

{t3:[0,82.5,0]}  

]);  

}  

};  

}  

if(name==='switch'){//obj文件中的一個(gè)模型名稱為switch  

model.mat={  

func:function(data){  

returnht.Default.createMatrix([  

{t3:[0,48.5,0]},  

{r3:[0,0,data.a('meter.angle')]},  

{t3:[0,-48.5,0]}  

]);  

}  

};  

model.color={  

func:function(data){  

if(data.a('meter.angle')){  

return'rgb(186,0,0)';  

}else{  

return'black';  

}  

}  

};  

}  

}  

ht.Default.setShape3dModel('meter',array);//注冊3D模型,請參考modeling建模手冊第一參數(shù)為模型名稱,第二參數(shù)為JSON類型對(duì)象  

之后用戶可以在需要用到的地方直接設(shè)置屬性shape3d為這邊注冊過的3D模型名稱,我們下面就創(chuàng)建3個(gè)節(jié)點(diǎn),并將節(jié)點(diǎn)設(shè)置為此3D模型:  

for(vari=0;i<3;i++){//創(chuàng)建3個(gè)節(jié)點(diǎn)meter  

varnode=newht.Node();  

node.setTag(i);//設(shè)置tag標(biāo)簽  

node.setName('Meter-00'+(i+1));//設(shè)置圖元名稱一般顯示在圖元的下方  

node.s({  

'label.color':'white',  

'label.background':'#5271B8',  

'label.face':'center',  

'label.position':23,  

'label.scale':2,  

'label.reverse.flip':true,  

'note.scale':1.5,//設(shè)置字體大小,這種方式不會(huì)碰到瀏覽器最小字體的問題  

'note.t3':[-30,-5,-90],  

'note2.scale':1.2,  

'note2.position':17,  

'note2.t3':[0,-20,-30],  

'note2.color':'black',  

'note2.background':'yellow',  

'shape3d':'meter',//設(shè)置為前面注冊的meter3D模型  

'shape3d.scaleable':false,  

'wf.visible':'selected',//選中圖元時(shí)顯示線框  

'select.brightness':1  

});  

node.a({//自定義屬性下面會(huì)利用這些自定義屬性進(jìn)行數(shù)據(jù)綁定  

'meter.value':i+1,  

'meter.angle':i*Math.PI/3  

});  

node.p3(i*200-200,params.rawS3[1]/2,i===1?100:-100);  

node.r3(0,-Math.PI/6*(i-1),0);  

node.s3(params.rawS3);//設(shè)置圖元的大小為rawS3模型的原始尺寸  

dataModel.add(node);//向數(shù)據(jù)模型中添加節(jié)點(diǎn)  

}  

dataModel.sm().ss(dataModel.getDataByTag(1));//設(shè)置默認(rèn)選中tag標(biāo)簽為1的圖元  

我們在這邊為節(jié)點(diǎn)添加兩個(gè)標(biāo)注,作為文字提示,可以通過重載getNote/getNote2(HT中一個(gè)節(jié)點(diǎn)支持雙標(biāo)注,所以提供了note2第二個(gè)標(biāo)注)函數(shù)重載note的命名方法,當(dāng)然HT中其他類似的文字提示也可以通過這種途徑來改變文字的顯示信息,這里我們通過數(shù)據(jù)綁定獲取meter.value以及meter.angle兩個(gè)屬性的動(dòng)態(tài)數(shù)據(jù):  

g3d.getNote=function(data){//重載getNote方法  

return'Value:'+data.a('meter.value').toFixed(2);  

};  

g3d.getNote2=function(data){  

varvalue=Math.round(data.a('meter.angle')/Math.PI*180);//獲取了meter.angle屬性,數(shù)據(jù)實(shí)時(shí)變化  

returnvalue?'Angle:'+value:'Switchisoff';  

};  

我們還在場景的顯示部分使了一點(diǎn)小心機(jī)~通過改變實(shí)現(xiàn)eye和center的值來實(shí)現(xiàn)視線由遠(yuǎn)及近的效果:  

varoldEye=g3d.getEye().slice(0),  

oldCenter=g3d.getCenter().slice(0),  

newEye=[200,300,650],  

newCenter=[0,params.rawS3[1]/2,0];  

ht.Default.startAnim({//動(dòng)畫  

duration:1000,//持續(xù)時(shí)間  

easing:function(t){//動(dòng)畫緩動(dòng)函數(shù),默認(rèn)采用ht.Default.animEasing  

return(t*=2)<1?0.5*t*t:0.5*(1-(--t)*(t-2));  

},  

action:function(k){//action函數(shù)必須提供,實(shí)現(xiàn)動(dòng)畫過程中的屬性變化參數(shù)k代表通過easing(t)函數(shù)運(yùn)算后的值  

g3d.setEye(  

oldEye[0]+(newEye[0]-oldEye[0])*k,  

oldEye[1]+(newEye[1]-oldEye[1])*k,  

oldEye[2]+(newEye[2]-oldEye[2])*k  

);  

g3d.setCenter(  

oldCenter[0]+(newCenter[0]-oldCenter[0])*k,  

oldCenter[1]+(newCenter[1]-oldCenter[1])*k,  

oldCenter[2]+(newCenter[2]-oldCenter[2])*k  

);  

}  

});  

整個(gè)左邊實(shí)現(xiàn)完成~接著該實(shí)現(xiàn)右上部分,屬性值的顯示以及控制,我們總共添加了四個(gè)屬性:名稱、meter.value、meter.angle以及旋轉(zhuǎn)rotation,通過數(shù)據(jù)綁定操作屬性欄中的值來改變3D模型中的顯示狀態(tài),數(shù)據(jù)綁定我們通過獲取accessType以及name中的值來配合調(diào)用到這個(gè)屬性:  

propertyView.addProperties([//用json的數(shù)組參數(shù)方式批量添加屬性信息  

{  

name:'name',//屬性名這里不用設(shè)置accessType,因?yàn)閍ccessType默認(rèn)的值為setName/getName這種格式  

editable:true//設(shè)置為可編輯狀態(tài)  

},  

{  

name:'meter.value',//用于存取name屬性,該屬性結(jié)合accessType屬性最終實(shí)現(xiàn)對(duì)Data屬性的存取  

accessType:'attr',//通過getAttr/setAttr獲取或設(shè)置屬性值  

editable:true,  

slider:{  

min:0,  

max:4  

}  

},  

{  

name:'meter.angle',  

accessType:'attr',  

editable:true,  

formatValue:function(value){//一般用于將數(shù)字轉(zhuǎn)換更易讀的文本格式  

returnMath.round(value/Math.PI*180);  

},  

slider:{  

min:0,  

max:Math.PI,  

step:Math.PI/180*5,//每移動(dòng)一下滑動(dòng)的步進(jìn)  

getToolTip:function(){//設(shè)置鼠標(biāo)放在圖元上的文字提示  

returnMath.round(this.getValue()/Math.PI*180);  

}  

}  

},  

{  

name:'rotation',  

editable:true,  

formatValue:function(value){  

returnMath.round(value/Math.PI*180);  

},  

slider:{  

min:-Math.PI,  

max:Math.PI,  

step:Math.PI/180*5,  

getToolTip:function(){  

returnMath.round(this.getValue()/Math.PI*180);  

}  

}  

}  

]);  

最后進(jìn)行右下部分formPane表單面板的解析,formPane通過addRow函數(shù)向表單中添加行,這個(gè)表單中總共兩行,其中第一行有兩個(gè)部分:  

formPane.addRow([//向表單組件中添加行  

{  

id:'export',  

button:{//按鈕  

label:'ExportJSON',  

onClicked:function(){//點(diǎn)擊時(shí)觸發(fā)的函數(shù)  

varjson=dataModel.serialize();  

formPane.v('textArea',json);  

}  

}  

},  

{  

button:{  

label:'ImportJSON',  

onClicked:function(){  

dataModel.clear();//清空數(shù)據(jù)模型  

dataModel.deserialize(formPane.v('textArea'));//將獲取到的textArea中的數(shù)據(jù)反序列化,是下面一行的id值  

}  

}  

}  

],  

[0.1,0.1]);//最后的參數(shù)是這行的寬度分配比例小于1的值為比例,大于1為實(shí)際值  

formPane.addRow([  

{  

id:'textArea',  

textArea:{  

}  

}  

],  

[0.1],0.1);  

最后這樣我們就可以根據(jù)修改屬性欄中或者JSON文件,直接看到3D中我們修改的效果啦了。


*博客內(nèi)容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀點(diǎn),如有侵權(quán)請聯(lián)系工作人員刪除。



關(guān)鍵詞:

相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉