博客專欄

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

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

        發布人:扣丁學堂 時間:2020-06-30 來源:工程師 發布文章

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

        333.png

          

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

        //場景搭建  

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

        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場景中,這時我們可以向圖元中添加各種屬性和樣式以及標簽作為標記,本例中用到的圖元是3D模型,利用ht.Default.parseObj函數對obj和mtl文件進行解析:  

        //添加模型  

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

        varmodelMap=ht.Default.parseObj(meter_obj,meter_mtl,params);//解析obj和mtl文件,解析后返回的map結構json對象中,每個材質名對應一個模型信息  

        當然,前提是要已經聲明了meter_obj以及meter_mtl兩個文件,這里我們是將這兩個部分分別放到js文件中,并在頭部調用。  

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

        vararray=[];  

        for(varnameinmodelMap){  

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

        array.push(model);  

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

        model.mat={//矩陣變化參數,可對模型進行矩陣變化后導入  

        func:function(data){  

        varstart=Math.PI*0.736,  

        range=Math.PI*1.49,  

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

        returnht.Default.createMatrix([//將一組JSON描述的縮放、移動和旋轉等操作轉換成對應的變化矩陣  

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

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

        {t3:[0,82.5,0]}  

        ]);  

        }  

        };  

        }  

        if(name==='switch'){//obj文件中的一個模型名稱為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建模手冊第一參數為模型名稱,第二參數為JSON類型對象  

        之后用戶可以在需要用到的地方直接設置屬性shape3d為這邊注冊過的3D模型名稱,我們下面就創建3個節點,并將節點設置為此3D模型:  

        for(vari=0;i<3;i++){//創建3個節點meter  

        varnode=newht.Node();  

        node.setTag(i);//設置tag標簽  

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

        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,//設置字體大小,這種方式不會碰到瀏覽器最小字體的問題  

        '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',//設置為前面注冊的meter3D模型  

        'shape3d.scaleable':false,  

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

        'select.brightness':1  

        });  

        node.a({//自定義屬性下面會利用這些自定義屬性進行數據綁定  

        '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);//設置圖元的大小為rawS3模型的原始尺寸  

        dataModel.add(node);//向數據模型中添加節點  

        }  

        dataModel.sm().ss(dataModel.getDataByTag(1));//設置默認選中tag標簽為1的圖元  

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

        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屬性,數據實時變化  

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

        };  

        我們還在場景的顯示部分使了一點小心機~通過改變實現eye和center的值來實現視線由遠及近的效果:  

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

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

        newEye=[200,300,650],  

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

        ht.Default.startAnim({//動畫  

        duration:1000,//持續時間  

        easing:function(t){//動畫緩動函數,默認采用ht.Default.animEasing  

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

        },  

        action:function(k){//action函數必須提供,實現動畫過程中的屬性變化參數k代表通過easing(t)函數運算后的值  

        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  

        );  

        }  

        });  

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

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

        {  

        name:'name',//屬性名這里不用設置accessType,因為accessType默認的值為setName/getName這種格式  

        editable:true//設置為可編輯狀態  

        },  

        {  

        name:'meter.value',//用于存取name屬性,該屬性結合accessType屬性最終實現對Data屬性的存取  

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

        editable:true,  

        slider:{  

        min:0,  

        max:4  

        }  

        },  

        {  

        name:'meter.angle',  

        accessType:'attr',  

        editable:true,  

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

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

        },  

        slider:{  

        min:0,  

        max:Math.PI,  

        step:Math.PI/180*5,//每移動一下滑動的步進  

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

        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);  

        }  

        }  

        }  

        ]);  

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

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

        {  

        id:'export',  

        button:{//按鈕  

        label:'ExportJSON',  

        onClicked:function(){//點擊時觸發的函數  

        varjson=dataModel.serialize();  

        formPane.v('textArea',json);  

        }  

        }  

        },  

        {  

        button:{  

        label:'ImportJSON',  

        onClicked:function(){  

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

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

        }  

        }  

        }  

        ],  

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

        formPane.addRow([  

        {  

        id:'textArea',  

        textArea:{  

        }  

        }  

        ],  

        [0.1],0.1);  

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


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞:

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 高青县| 西昌市| 成武县| 新兴县| 屏山县| 樟树市| 长海县| 福泉市| 突泉县| 武强县| 新干县| 廉江市| 巴南区| 府谷县| 民乐县| 耿马| 广平县| 樟树市| 衢州市| 松滋市| 太和县| 龙山县| 六安市| 绥芬河市| 隆回县| 泰顺县| 霍林郭勒市| 普格县| 淮北市| 大石桥市| 两当县| 洛阳市| 托克托县| 彭州市| 六安市| 夹江县| 运城市| 奉化市| 东兴市| 莎车县| 九龙城区|