1. 程式人生 > >工控SCADA模型 基於HTML5 Canvas WebGL制作摩托車

工控SCADA模型 基於HTML5 Canvas WebGL制作摩托車

調整 radi 面板 -s span .cn sele 詳情 分析

工業方面制作圖表,制作模型方面運用到 3d 模型是非常多的,在一個大的環境中,構建無數個相同的或者不同的模型,構建起來對於程序員來說也是一件相當頭疼的事情,我們利用 HT 幫大家解決了很大的難題,以下例子可在官網上查找到 http://hightopo.com/demos/index.html:

技術分享

技術分享

技術分享

這些都是工業控制上的一些實例,只要你有想法,你就能把這些實現得更好。

本文 Demo 地址: http://hightopo.com/guide/guide/plugin/obj/examples/example_objajax.html

這次我們的例子是將這些實例中的一小部分思想抽取出來,作為給大家的分析,看看這次實現的例子效果圖:

技術分享

這個例子用了 HT 中的樹組件 ht.widget.TreeView 和 HT 中加載 OBJ 格式文件的 ht.Default.loadObj 函數來加載圖中的兩輛摩托車,我們利用代碼來從頭開始解析這個例子的部分。

首先觀察這個例子的界面展示,會發現這個界面是由左右兩部分組成的,右邊又是由上下兩部分組成的,這種分割模式在 HT 中有很好的解決辦法,可以完全利用 ht.widget.SplitView 將界面分層,也可以利用 ht.widget.BorderPane 將界面分成上面、中間和下面。這裏我們因為是示例,所以將兩種方法都用上了:

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個元素,也具有足夠的代表性:

 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 工具條組件手冊。

接著要將最外層的組件添加進底層 div 中,沒有閱讀過我的文章的同學這邊我解釋一下,所有的 HT 組件最根層都是一個 div 組件,可通過組件的 getView 函數獲得,默認和自定義交互時間監聽一般添加在該 div 上(getView().addEventListener(type, func, false)),渲染層一般由 canvas 提供,用戶可直接對根 div 和 canvas 層設置 css 樣式,也可以添加新的 HTML 組件到根 div 上,作為 canvas 的兄弟組件一起呈現。詳情請參考 HT for Web 入門手冊。

接著通過利用 ht.widget.loadObj 函數將 OBJ 格式文件導入模型:

 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 函數來設置多選框,這個函數的參數可為:

  • null:默認值,不啟用check選擇模式
  • default:check模式的默認選擇方式,即單擊選中或取消選中,只影響當前點擊中的data對象
  • children:該check模式將同時影響點擊中的data對象,以及其孩子對象
  • descendant:該check模式將同時影響點擊中的data對象,以及其所有子孫對象
  • all:該check模式將同時影響點擊中的data對象,以及其所有父輩和子孫對象

如果還是沒有理解,大家可以試試將這個函數註釋掉,你就能很清楚地明白它是做什麽用的了。或者查看 HT for Web 樹組件手冊。

以上就是今天的例子,實際開發中的例子會更復雜,邏輯也會更多,但通過 HT 來做,什麽事情都變得 so easy!

工控SCADA模型 基於HTML5 Canvas WebGL制作摩托車