基於 HTML5 Canvas 2D 拓撲圖和 3D 機櫃模型的增刪操作
今天好好地消化了一下我們的資料容器 DataModel,這裡給初學者做一個典型的資料模型事件處理的例子作為參考。這個例子看起來很簡單,實際上結合了資料模型中非常重要的三個事件處理的部分:屬性變化事件監聽、選中變化事件監聽以及資料模型變化事件監聽。
為了讓這個例子具現化,我將這個簡單的例子做了一點改動,下面我會一一解釋。
例子地址:http://hightopo.com/guide/guide/core/datamodel/examples/example_datamodel.html
這是我改造之後的模樣,將 dataModel 資料容器共享,通過對資料容器的增刪事件的監聽得到的現在的結果,並且在顯示上做了一點“手腳”。下面我們從頭解析這例子,你們會知道為什麼我特地將這個簡單的例子提出來。
首先,我們得建立場景將作為基礎,整個場景我算是分為三個部分,頂部工具欄,2D 部分以及 3D 部分。頂部工具欄部分使用的純 HTML 寫的:
<button onclick="addData()">Add</button>
<button onclick="removeData()">Remove</button>
<button onclick="clearDataModel()">Clear</button>
<span id="property" class="output"></span>
<span id="model" class="output"></span>
<span id="selection" class="output"></span>
因為有點選事件,所以我們直接在 button 按鈕上進行,後面的 span 標籤顯示純文字內容。
我們知道,HT 的所有元件都是基於一個根部 div 的,要將這個 div 部署到 html 頁面上很簡單,但是 HT 內部對這個 div 設定了絕對定位,所以我們在新增這個 div 進 HTML 頁面中時,也要設定絕對定位中的位置,我在頁面中新增了一個 div,將 HT 的部分都新增進這個 div 中:
<div id="myDiv" style="border: 1px solid red; width: 800px; height: 600px;position: absolute; "></div>
dataModel = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dataModel);
g3d.setGridVisible(true); // 設定網格可見
g3d.setEye(185, 50, 470); // 設定 3d 的眼睛位置
g3d.setCenter(200, 47, 10); // 設定 3d 的中心位置, 這兩個屬性都是為了讓使用者看 3d 上的場景更舒服,更直接
g2d = new ht.graph.GraphView(dataModel);
g2d.setEditable(true); // 設定 2d 圖元可編輯
g2d.fitContent(true); // 將所有的圖元顯示到頁面上
splitView = new ht.widget.SplitView(g2d, g3d, 'v', 0.3); // 分割元件,裝了2d 和 3d 兩個場景
splitView.addToDOM(); // 將分割元件新增進 body 中,並設定絕對定位的位置
myDiv = document.getElementById('myDiv');
myDiv.appendChild(splitView.getView()); // 將分割元件新增進 myDiv 中
接著新增節點進入 dataModel 資料模型之中,我們這裡做的是機房的機櫃,本來想做的是伺服器,手頭上暫時只有這個資源,也不賴。我封裝了一個增加函式,一個刪除函式,還有一個清楚函式,分別對應的是工具欄上的“Add”、“Remove”以及“Clear”三個功能:
function addData() {
var data = new ht.Node();
data.setPosition(index*60, 50);
data.setName('node'+index);
data.setSize(40, 40);
data.setImage('cabinet');
data.s({
'image.stretch': 'centerUniform',
'shape3d': 'cabinet'
});
index++;
dataModel.add(data);
return data;
}
function removeData() {
if(!dataModel.sm().ld()) return;
dataModel.remove(dataModel.sm().ld());
}
function clearDataModel(){
dataModel.clear();
index = 0;
}
其中,程式碼中出現的“data.setImage(‘cabinet’)”,是我通過 ht.Default.setImage(‘cabinet’, ‘imageURL’) 方式定義的,呼叫的時候直接 data.setImage(‘imageName’) 即可,具體參考 HT for Web 入門手冊 image 章節。
2D 的圖片顯示肯定和 3D 的模型顯示是不一樣的,2D 中我們直接用貼圖就能解決,而 HT 3D 中支援 obj 格式的模型顯示,就是這個部分:
HT 封裝瞭解析 obj 格式的函式 ht.Default.loadObj 函式用來匯入模型,該函式有三個引數,第一第二分別為 obj 檔案的路徑和 mtl 檔案的路徑,第三個引數為 json 格式控制引數,具體引數請參考 HT for Web OBJ 手冊 loadObj 函式章節(ps:用 obj 模型會導致跨域問題,要放到伺服器上執行):
ht.Default.loadObj('obj/機櫃元件1.obj', 'obj/機櫃元件1.mtl', {
cube: true, // 是否將模型縮放到單位1的尺寸範圍內,預設為 false
center: true, // 模型是否居中
prefix: 'obj/', // 路徑字首,如果前面引數寫了路徑字首,這個不寫也可以
shape3d: 'cabinet', // 指定 shape3d 名稱
finishFunc: function(modelMap, array, rawS3){ // 呼叫 ht.Default.parseObj 解析後的返回值,若載入或解析失敗則返回值為空
window.rawS3 = rawS3; // 讓當前模型的尺寸為原始尺寸
if(modelMap){
cabinet1 = addData(); // 新增兩個節點到 dataModel 中
cabinet2 = addData();
}
}
});
現在,節點和模型都已經匯入到場景中了,終於來到了我們今天的重點,事件互動部分。ht.DataModel 資料容器管理著 Data 資料的增刪以及變化事件的派發,這裡我們就這兩種事件進行對 Data 資料的管理。
-
addDataModelChangeListener(function(e) {}, scope)
增加資料模型增刪變化事件監聽器,可用簡寫 mm(func, scope), func 為監聽器函式,scope
為監聽器函式域(可選),在監聽器函式中的 event 有兩個屬性: kind 和 data,其中 kind 為事件的型別:e.kind === 'add’代表新增Data物件,e.data 為被新增的物件
e.kind ==='remove’代表刪除Data物件,e.data 為被刪除的物件
e.kind === 'clear’代表容器被清除
這裡我們將對模型的增刪事件的監聽結果傳給 HTML 中的 id 為 model 的 span 作為內容:
var model = document.getElementById('model');
dataModel.addDataModelChangeListener(function(e) {
if(e.kind === 'add') // 如果事件型別為 add 增加節點
model.innerHTML = e.data + ' added'; // 就將model 的內容替換為新增的節點 added
if(e.kind === 'remove')
model.innerHTML = e.data + ' removed';
if(e.kind === 'clear')
model.innerHTML = 'dataModel cleared'
});
-
addDataPropertyChangeListener(function(e) {}, scope) 增加模型中 Data
資料屬性變化事件監聽器,可用簡寫 md(func, scope),其中 event 事件有四種屬性:e.data 代表屬性變化的物件
e.property 代表變化屬性的名字
e.newValue 代表屬性的新值
e.oldValue 代表屬性的老值
Data 物件在設定屬性值函式內呼叫 firePropertyChange(property, oldValue, newValue) 觸發屬性變化事件:
get/set 型別屬性,如 setAge(98) 觸發事件的 e.property為age
style 型別屬性名前加 s: 字首以區分,如 setStyle(‘age’, 98) 觸發事件的 e.property為s:age
attr 型別屬性名前加 a: 字首以區分,如 setAttr(‘age’, 98) 觸發事件的 e.property為a:age
這裡我們將對模型中 Data 的屬性變化事件的監聽結果傳給 HTML 中的 id 為 property 的 span 作為內容:
var model = document.getElementById('model');
dataModel.addDataPropertyChangeListener(function(e) {
property.innerHTML = e.data + '\'s ' + e.property + ' has changed, the old value is ' + e.oldValue + ' and the new value is ' + e.newValue;
});
- 最後,我們對選中的節點進行增加監聽器,監聽選中變化事件。ht.SelectionModel管理 DataModel 模型中 Data
物件的選擇狀態, 每個 DataModel 物件都內建一個 SelectionModel 選擇模型,控制這個
SelectionModel 即可控制所有繫結該 DataModel 的元件的物件選擇狀態, 這意味著共享同一 DataModel
的元件預設就具有選中聯動功能。
如果希望某些元件不與其他元件選中聯動,可通過呼叫 view.setSelectionModelShared(false), 這樣該 view 將建立一個專屬的 SelectionModel 例項。
綜上所述有兩種途徑可得到 SelectionModel:
dataModel.getSelectionModel() 獲取資料容器中元件共享的選中模型。
view.getSelectionModel() 獲取當前元件使用的選中模型,selectionModelShared 為false時,返回 view 專用的選擇模型。
addSelectionChangeListener(function(e) {}, scope) 增加監聽器,監聽選中變化事件,簡寫為 ms(func, scope):
e.datas 包含所有選中狀態變化的物件,之前選中現在取消選中,或之前沒選中現在被選中的物件
e.kind === ‘set’ 代表此事件由 setSelection(datas) 引發
e.kind === ‘remove’ 代表此事件由 removeSelection(datas) 引發
e.kind === ‘append’ 代表此事件由 appendSelection(datas) 引發
e.kind === ‘clear’ 代表此事件由 clearSelection(datas) 引發
這裡我們將對模型中 Data 的選中變化事件的監聽結果傳給 HTML 中的 id 為 selection 的 span 作為內容:
var selection = document.getElementById('selection');
dataModel.sm().addSelectionChangeListener(function(e){
if(dataModel.sm().size() === 0) selection.innerHTML = 'Nothing selected'; // 如果選中模型的“長度”為 0,即沒有選中內容
else if(dataModel.sm().size() === 1) selection.innerHTML = e.datas + ' selected';
else selection.innerHTML = dataModel.sm().size() + ' datas selected';
});
以上,所有的程式碼全部分析完畢!大家可以天馬行空,建立出屬於你自己的 3 維模型!
相關文章
- 基於HTML5 Canvas 點選新增 2D 3D 機櫃模型HTMLCanvas3D模型
- 基於 HTML5 WebGL 的 3D 網路拓撲圖HTMLWeb3D
- 基於 WebGL 的 HTML5 3D 網路拓撲圖WebHTML3D
- 基於 HTML5 Canvas 電信網路拓撲圖的快速搭建HTMLCanvas
- 基於 HTML5 Canvas 繪製的電信網路拓撲圖HTMLCanvas
- 基於 HTML5 Canvas 的拓撲元件 ToolTip 應用HTMLCanvas元件
- 基於 WebGL 的 HTML5 網路拓撲結構 3D 圖WebHTML3D
- 基於 HTML5 WebGL 的 3D 網路拓撲結構圖HTMLWeb3D
- HTML5的WebGL實現的3D和2D拓撲樹HTMLWeb3D
- 基於 HTML5 Canvas 的 3D 模型貼圖問題HTMLCanvas3D模型
- 基於HTML5的3D網路拓撲樹呈現HTML3D
- 基於 HTML5 的 3D 網路拓撲樹呈現HTML3D
- 基於HTML5 WebGL 將拓撲圖和圖表繪製在 3D 六面體上HTMLWeb3D
- 基於HTML5的3D網路拓撲自動佈局HTML3D
- 基於 Canvas 的 HTML5 工控機櫃 U 位動態管理CanvasHTML
- 基於 HTML5 Canvas 的工控機櫃 U 位動態管理HTMLCanvas
- 快速建立 HTML5 Canvas 電信網路拓撲圖HTMLCanvas
- 基於 HTML5 Canvas 的簡易 2D 3D 編輯器HTMLCanvas3D
- 基於 HTML5 Canvas 的電信機櫃 U 位動態管理HTMLCanvas
- 基於 HTML5 Canvas 的 3D 機房建立HTMLCanvas3D
- 快速開發基於 HTML5 網路拓撲圖應用HTML
- 快速開發基於 HTML5 網路拓撲圖應用1HTML
- 基於HT for Web的3D拓撲樹的實現Web3D
- 基於 HTML5 Canvas 的 3D 熱力雲圖效果HTMLCanvas3D
- 基於HTML5 Canvas的3D動態Chart圖表HTMLCanvas3D
- 基於 HTML5 Canvas 實現的 TP-LINK 電信拓撲裝置皮膚HTMLCanvas
- 基於 HTML5 的網路拓撲圖之 DataBinding 資料繫結HTML
- 基於 HTML5 網路拓撲圖的快速開發之入門篇(二)HTML
- 基於 HTML5 網路拓撲圖的快速開發之入門篇(一)HTML
- 基於d3.js的關係拓撲圖JS
- 基於 HTML5 Canvas 的 3D 碰撞檢測HTMLCanvas3D
- 快速開發基於 HTML5 網路拓撲圖應用--入門篇(一)HTML
- 快速開發基於 HTML5 網路拓撲圖應用--入門篇(二)HTML
- HTML5 網路拓撲圖效能優化HTML優化
- 基於 WebSocket 實現 WebGL 3D 拓撲圖實時資料通訊同步(一)Web3D
- 基於 WebSocket 實現 WebGL 3D 拓撲圖實時資料通訊同步(二)Web3D
- 向量化的HTML5拓撲圖形元件設計HTML元件
- 基於HTML5Canvas的工控機櫃U位動態管理HTMLCanvas