工業方面製做圖表,製做模型方面運用到 3d 模型是很是多的,在一個大的環境中,構建無數個相同的或者不一樣的模型,構建起來對於程序員來講也是一件至關頭疼的事情,咱們利用 HT 幫你們解決了很大的難題,無數個例子可在官網上查找到 http://hightopo.com/demos/index.htmlcss
本文 Demo 地址: http://hightopo.com/guide/guide/plugin/obj/examples/example_objajax.htmlhtml
此次咱們的例子是將這些實例中的一小部分思想抽取出來,做爲給你們的分析,看看此次實現的例子效果圖:node
這個例子用了 HT 中的樹組件 ht.widget.TreeView 和 HT 中加載 OBJ 格式文件的 ht.Default.loadObj 函數來加載圖中的兩輛摩托車,咱們利用代碼來從頭開始解析這個例子的部分。程序員
首先觀察這個例子的界面展現,會發現這個界面是由左右兩部分組成的,右邊又是由上下兩部分組成的,這種分割模式在 HT 中有很好的解決辦法,能夠徹底利用 ht.widget.SplitView 將界面分層,也能夠利用 ht.widget.BorderPane 將界面分紅上面、中間和下面。這裏咱們由於是示例,因此將兩種方法都用上了:ajax
1 dataModel = new ht.DataModel();//數據模型 2 g3d = new ht.graph3d.Graph3dView(dataModel);//3d組件 3 toolbar = new ht.widget.Toolbar(item); //工具條 4 borderPane = new ht.widget.BorderPane();//面板組件 5 borderPane.setTopView(toolbar);//toolbar 放在上部 6 borderPane.setCenterView(g3d);//g3d 放在中間部分 7 treeView = new ht.widget.TreeView(dataModel); //樹組件 8 mainSplit = new ht.widget.SplitView(treeView, borderPane, 'h', 0.2); //分割組件
其中 toolbar 中的 item 也是遵照 HT 設置規則的,item 是一個數組,數組中每個元素都是toolbar上的一部分,這個例子中toolbar只有2個元素,也具備足夠的表明性:json
1 item = [ 2 { 3 label: 'Editable', 4 type: 'check', 5 action: function(){ 6 g3d.setEditable(this.selected); 7 } 8 }, 9 { 10 id: 'size', 11 label: 'Size', 12 slider: { 13 width: 120, 14 min: 1, 15 max: 60, 16 value: 1, 17 thickness: 1, 18 onValueChanged: function(){ 19 if(rawS3){ 20 var value = this.getValue(); 21 dataModel.each(function(data){ 22 if(data instanceof ht.Node){ 23 data.s3(rawS3[0] * value, rawS3[1] * value, rawS3[2] * value); 24 data.s({ 25 'note.scale': value/20, 26 'note.t3': [0, -value, value] 27 }); 28 } 29 }); 30 } 31 } 32 ];
咱們能夠經過設置 toolbar 中的 item 元素來設置對象格式類型,其中 type 能夠設置爲 check、toggle 和 radio,分別表示複選框、開關按鈕和單選按鈕,這裏咱們將是否可編輯 Editable 設置爲複選框,能夠經過控制這個元素來設置是否可編輯,後面的拉條也是 HT 中封裝的 ht.Slider 滑動條來綁定 OBJ 對象的 size 大小,經過控制滑動條來控制 OBJ 的大小,詳情請參考 HT for Web 工具條組件手冊。canvas
接着要將最外層的組件添加進底層 div 中,沒有閱讀過個人文章的同窗這邊我解釋一下,全部的 HT 組件最根層都是一個 div 組件,可經過組件的 getView 函數得到,默認和自定義交互時間監聽通常添加在該 div 上(getView().addEventListener(type, func, false)),渲染層通常由 canvas 提供,用戶可直接對根 div 和 canvas 層設置 css 樣式,也能夠添加新的 HTML 組件到根 div 上,做爲 canvas 的兄弟組件一塊兒呈現。詳情請參考 HT for Web 入門手冊。數組
接着經過利用 ht.widget.loadObj 函數將 OBJ 格式文件導入模型:ide
1 ht.Default.loadObj('obj/scooter.obj', 'obj/scooter.mtl', {//左邊不可分割的摩托 2 cube: true, 3 center: true, 4 shape3d: 'scooter', 5 finishFunc: function(modelMap, array, rawS3){ 6 window.rawS3 = rawS3; 7 if(modelMap){ 8 var node = new ht.Node(); 9 node.setName('All in ONE'); 10 node.s({ 11 'shape3d': 'scooter', 12 'wf.visible': 'selected', 13 'note': 'One Node', 14 'note.face': 'center', 15 'note.position': 7, 16 'note.background': 'blue', 17 'note.autorotate': 'y' 18 }); 19 node.s3(rawS3); 20 node.p3(-300, 0, 0); 21 dataModel.add(node); 22 } 23 checkLoaded(); 24 } 25 });
ht.Default.loadObj 函數有三個參數,objUrl OBJ 文件路徑,mtlUrl MTL 文件路徑,params JSON 結構參數,parmas 參數能夠設置 ht.Default.parseObj(text, mtlMap, params) 第三個參數的控制信息,也就是說 ht.Default.parseObj 函數中的第三個參數所帶的控制信息在 ht.Default.loadObj 函數中的第三個參數 params 中均可以使用,而且添加了 sync 和 finishFunc 參數,finishFUnc 參數是用於加載後的回調處理的函數,帶有參數 modelMap、array 和 rawS3 ,能夠在 finishFunc 中作任何事情!詳情請參考 HT for Web OBJ 手冊。函數
本例中有兩個 motor 摩托車模型,一個是總體的模型,不能拆分,一個是能夠拆分紅部分的模型,接下來就來看看如何將 OBJ 文件中的模型拆分開來:
1 ht.Default.loadObj('obj/scooter.obj', 'obj/scooter.mtl', {//右邊可分割的摩托 2 3 cube: true, 4 center: true, 5 finishFunc: function(modelMap, array, rawS3){ 6 if(modelMap){ 7 var lastNode = null, 8 firstNode = null, 9 parentNode = new ht.Data(); 10 11 parentNode.setName('Separate Scooter'); 12 dataModel.add(parentNode); 13 14 for(var name in modelMap){ 15 var model = modelMap[name]; 16 var shape3d = 'scooter:' + name; 17 ht.Default.setShape3dModel(shape3d, model); 18 19 var node = new ht.Node(); 20 node.setName(name); 21 node.setParent(parentNode); 22 node.s({ 23 'shape3d': shape3d, 24 'wf.visible': 'selected' 25 }); 26 node.setHost(lastNode); 27 lastNode = node; 28 if(!firstNode){ 29 firstNode = node; 30 } 31 node.s3(rawS3); 32 dataModel.add(node); 33 } 34 if(lastNode){ 35 firstNode.setHost(lastNode); 36 firstNode.p3(300, 0, 0); 37 firstNode.s({ 38 'note': 'A lot of Nodes host together', 39 'note.face': 'center', 40 'note.position': 7, 41 'note.background': 'blue' 42 }); 43 } 44 } 45 checkLoaded(); 46 } 47 });
咱們能夠經過 modelMap 得到經過 ht.Default.parseObj 函數解析後的返回值,這個值一般就是 obj 格式的文件解析後返回的 map 結構的 json 對象,每個材質都對應一個模型信息,詳情請參考 HT for Web OBJ 手冊。
咱們利用 ht.Default.parseObj 函數解析得到每一個材質的模型信息,經過遍歷整個模型,得到單獨的模型信息,而且將其命名,這樣咱們就能顯示每一個模型的名稱了,也能對每一個部分的模型進行控制。
上面代碼中 45 行出現的 checkLoaded 函數是方便控制樹組件的展開合併的函數,咱們在工業等各個領域中,用到「樹」的概念是很是多的,因此這個例子也運用到用做解釋:
1 function checkLoaded(){ 2 loadTask--; 3 if(loadTask === 0){ 4 treeView.expandAll(); 5 treeView.selectAll(); 6 7 ht.Default.startAnim({ 8 action: function(t){ 9 toolbar.v('size', 50*t); 10 } 11 }); 12 } 13 }
由於「樹」的部分咱們只用了兩個主節點,All in one 和 Seperate Scooter,咱們定義 loadTask 變量值爲 2,上面代碼的意思是若是兩個模型都加載完畢,那麼就將樹組件 treeView 展開,而且所有選中,再用代碼控制 toolbar 中的值爲 50*t 來調整模型的大小。
對於樹組件 treeView,HT 封裝了不少幫助組件,使得開發速度更快,好比在這個例子中用到的 setSortFunc 函數,是用來設置排序的;setCheckMode 函數是用來設置 check 模式的,你們一看到 check 就會想到多選框,在這裏 HT 確實是經過設置 setCheckMode 函數來設置多選框,這個函數的參數可爲:
若是仍是沒有理解,你們能夠試試將這個函數註釋掉,你就能很清楚地明白它是作什麼用的了。或者查看 HT for Web 樹組件手冊。
以上就是今天的例子,實際開發中的例子會更復雜,邏輯也會更多,但經過 HT 來作,什麼事情都變得 so easy!