這篇文章主要介紹了 HTML5中Canvas的3D壓力器反序列化示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
東陽網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián)公司,東陽網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為東陽1000多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的東陽做網(wǎng)站的公司定做!
實(shí)踐場(chǎng)景再現(xiàn):
首先我們搭建一下這個(gè)例子的場(chǎng)景,熟悉的朋友可能已經(jīng)看出來了,這個(gè)場(chǎng)景分為三個(gè)部分:左、右上以及右下。HT 通過 ht.widget.SplitView 可以很輕松地將場(chǎng)景分割,實(shí)現(xiàn)良好的頁面布局,最后將這個(gè)分割組件添加進(jìn) html 的 body 體中:
//場(chǎng)景搭建 dataModel = new ht.DataModel();//數(shù)據(jù)容器 g3d = new ht.graph4d.Graph4dView(dataModel);//3D 組件 propertyView = new ht.widget.PropertyView(dataModel);// 屬性組件 formPane = new ht.widget.FormPane();//表單組件 rightSplit = new ht.widget.SplitView(propertyView, formPane, 'v', 100);//分割組件 new ht.widget.SplitView(g3d, rightSplit, 'h', 0.65).addToDOM();
接下來就是向場(chǎng)景中添加圖元,并把圖元添加到 3D 場(chǎng)景中,這時(shí)我們可以向圖元中添加各種屬性和樣式以及標(biāo)簽作為標(biāo)記,本例中用到的圖元是 3D 模型,利用 ht.Default.parseObj 函數(shù)對(duì) obj 和 mtl 文件進(jìn)行解析:
//添加模型 var params = {center: true};//JSON格式控制參數(shù) 傳入 ht.Default.parseObj 函數(shù)中 var modelMap = 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è)部分分別放到 js 文件中,并在頭部調(diào)用。
從上面的動(dòng)圖中我們可以看到,這個(gè)例子中需要變化的模型部分只有“指針”以及下面的“開關(guān)”兩個(gè)部分,所以我們通過遍歷的方式獲取這兩個(gè) obj 模型的部分,并注冊(cè) 3D 模型:
var array = []; for(var name in modelMap){ var model = modelMap[name];//modelMap 中的模型 array.push(model); if(name === 'pointer'){//obj 文件中的一個(gè)模型 名稱為 pointer model.mat = {//矩陣變化參數(shù),可對(duì)模型進(jìn)行矩陣變化后導(dǎo)入 func: function(data){ var start = Math.PI * 0.736, range = Math.PI * 1.49, angle = start - range * data.a('meter.value') / 4;//動(dòng)態(tài)獲取了 meter.value 的值 return ht.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){ return ht.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);//注冊(cè)3D模型,請(qǐng)參考modeling建模手冊(cè) 第一參數(shù)為模型名稱,第二參數(shù)為 JSON 類型對(duì)象
之后用戶可以在需要用到的地方直接設(shè)置屬性 shape3d 為這邊注冊(cè)過的 3D 模型名稱,我們下面就創(chuàng)建 3 個(gè)節(jié)點(diǎn),并將節(jié)點(diǎn)設(shè)置為此 3D 模型:
for(var i=0; i<3; i++){//創(chuàng)建3個(gè)節(jié)點(diǎn) meter var node = new ht.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è)置為前面注冊(cè)的 meter 3D 模型 '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的圖元
我們?cè)谶@邊為節(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){ var value = Math.round(data.a('meter.angle') / Math.PI * 180);//獲取了 meter.angle 屬性,數(shù)據(jù)實(shí)時(shí)變化 return value ? 'Angle:' + value : 'Switch is off'; };
我們還在場(chǎng)景的顯示部分使了一點(diǎn)小心機(jī)~通過改變實(shí)現(xiàn) eye 和 center 的值來實(shí)現(xiàn)視線由遠(yuǎn)及近的效果:
var oldEye = 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)?nbsp;accessType 默認(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)換更易讀的文本格式 return Math.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)放在圖元上的文字提示 return Math.round(this.getValue() / Math.PI * 180); } } }, { name: 'rotation', editable: true, formatValue: function(value){ return Math.round(value / Math.PI * 180); }, slider: { min: -Math.PI, max: Math.PI, step: Math.PI/180*5, getToolTip: function(){ return Math.round(this.getValue() / Math.PI * 180); } } } ]);
最后進(jìn)行右下部分 formPane 表單面板的解析,formPane 通過 addRow 函數(shù)向表單中添加行,這個(gè)表單中總共兩行,其中第一行有兩個(gè)部分:
formPane.addRow([//向表單組件中添加行 { id: 'export', button: {//按鈕 label: 'Export JSON', onClicked: function(){//點(diǎn)擊時(shí)觸發(fā)的函數(shù) var json = dataModel.serialize(); formPane.v('textArea', json); } } }, { button: { label: 'Import JSON', 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);
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“ HTML5中Canvas的3D壓力器反序列化示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!