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