天天看點

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統

檔案管理系統是通過建立統一的标準以規範整個檔案管理,包括規範各業務系統的檔案管理的完整的檔案資源資訊共享服務平台,主要實作檔案流水化采集功能。為企事業機關的檔案現代化管理,提供完整的解決方案,檔案管理系統既可以自成系統,為使用者提供完整的檔案管理和網絡查詢功能,也可以與本機關的OA辦公自動化和DPM設計過程管理,或者與MIS資訊管理系統相結合,形成更加完善的現代化資訊管理網絡。傳統檔案館随着社會的快速發展與變化,其内在形式上也發生了巨大變化,逐漸演變為現代智慧檔案館。智慧檔案館以現代科技為依托,充分結合現代物聯網技術與雲計算技術建構完善的城市智慧檔案,實作了現代社會全面管理的目标。本文以目前流行的 H5 技術為主,為現代智慧檔案館提供一套 WEB 解決方案。

前言

檔案管理系統是通過建立統一的标準以規範整個檔案管理,包括規範各業務系統的檔案管理的完整的檔案資源資訊共享服務平台,主要實作檔案流水化采集功能。為企事業機關的檔案現代化管理,提供完整的解決方案,檔案管理系統既可以自成系統,為使用者提供完整的檔案管理和網絡查詢功能,也可以與本機關的OA辦公自動化和DPM設計過程管理,或者與MIS資訊管理系統相結合,形成更加完善的現代化資訊管理網絡。傳統檔案館随着社會的快速發展與變化,其内在形式上也發生了巨大變化,逐漸演變為現代智慧檔案館。智慧檔案館以現代科技為依托,充分結合現代物聯網技術與雲計算技術建構完善的城市智慧檔案,實作了現代社會全面管理的目标。本文以目前流行的 H5 技術為主,為現代智慧檔案館提供一套 WEB 解決方案。

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統

代碼實作

場景搭建

在本例中,将使用 HT UI 元件對頁面實作布局;使用 RelativeLayout 相對布局器将頁面分為三個部分:left, top, center,使用 VBoxLayout 縱向布局器将 LEFT 部分分為 logo,editor,chart 三個部分

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統

Graph3dView 加載 3D 場景

Graph3dView 是 HT(www.hightopo.com) 元件中加載 3D 模型的拓撲元件,RelativeLayout 則是 HT 提供的 UI 解決方案,UI 元件中提供 HTView 元件來實作拓撲與 UI 的融合。

// 初始化相對布局器
    var relativeLayout = new ht.ui.RelativeLayout();
    // 初始化 3D 拓撲
    var g3dView = new ht.graph3d.Graph3dView();
    // 初始化 HTVIEW 元件, 并将 3D 拓撲放入其中
    var htView = new ht.ui.HTView(g3dView);
    // 布局器加載 HTVIEW 元件
    relativeLayout.addView(htView, {
        width: \'match_parent\',  // 填滿
        height: \'match_parent\', // 填滿
        marginTop: 64,            // 為 TOP 留下空間
        marginLeft: 250            // 為 LEFT 留下空間
  });
      

建立 LEFT 中的檔案袋模型

左側的 EDITOR 部分使用 HT 的調色闆元件(ht.widget.Palette), 将檔案袋添加到調色闆上,并設定為可以拖拽:

  var palette = new ht.widget.Palette();
    // palette 面闆是将圖元都分在“組”裡面,然後向“組”中添加圖元即可
    var group = new ht.Group();
    // 設定分組為打開的狀态
    group.setExpanded(true);
    // 設定組的說明
    group.setName(\'基礎圖元\');
    palette.dm().add(group);
    
    // 添加子圖元
    var childNode = new ht.Node();
    childNode.setParent(group);
    childNode.setName(name);
    childNode.setImage(image);
    childNode.s({
        \'draggable\': true,                     // true 為可拖拽 
        \'image.stretch\': \'centerUniform\'    // 圖檔申展方式
    });
    palette.dm().add(childNode);      

實作從調色闆中将圖元拖拽至 3D 場景

在上一步中我們對調色闆中的圖元屬性設定了可拖拽,此時可以實作拖拽圖元的動畫。但是并不能直接将圖元拖拽到 3D 場景中,實作思路是:

1.  在拖拽時擷取拖拽的圖元資訊

2.  拖拽到對應位置時顯示可擺放位置

3.  結束拖拽後在對應位置建立對應的 3D 模型 

對應代碼實作如下:

拖拽時擷取圖元資訊

g3dView.getView().addEventListener(\'dragover\', function(e) {
        e.preventDefault();
        var paletteNode = palette.dm().sm().ld();// 擷取 palette 上最後選中的節點 
        if (!paletteNode || !g3d.getDataAt(e)) return;
        
        // 擷取滑鼠下的節點
        var data = g3d.getDataAt(e);
        if (data.s(\'shape3d\') === \'檔案櫃.json\') {
            // 記錄檔案袋拖拽到的是哪個檔案櫃
            g3dView._focusData = data;
        }

    });      

拖拽到對應位置時建立 3D 模型,在實際實作過程中由于很難準确地擷取到檔案櫃中每一個可以擺放檔案袋的坐标位置,是以在本例中采用了預置的方法。具體原理就是在先建立一個正常不可見的檔案櫃模型,并在其中将檔案袋都擺放完整,在拖拽時,将此不可見的模型與将要擺放的模型重合,此時隻需判斷滑鼠所在的點下是否存在預置的模型存在就可以知道該處是否可以建立 3D 模型,實作效果如下:

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統
g3dView.getView().addEventListener(\'dragover\', function(e) { 
        ... // 舊邏輯省略
        
        // 拖拽下來的時候設定 所有的 displayName 為 box 的節點 為可見 (這樣拖拽才能擷取到預置模型)
        array.forEach(function(data) {
            data.s(\'3d.visible\', true);
        });

        var data = g3d.getDataAt(e);
        if (data.s(\'shape3d\') === \'檔案櫃.json\') {
            // 記錄檔案袋拖拽到的是哪個檔案櫃
            g3dView._focusData = data;

            // 将預置模型移動到拖拽的櫃子坐标
            shelf.p3(data.p3());
        }

        if(data.getDisplayName() === \'box\') {
            // 将對應坐标下預置的檔案袋模型進行顯示
            // 該屬性可修改模型的透明度,更多屬性可參考 HT 風格手冊
            data.s(\'shape3d.opacity\',  0.8);
        }
        ...
    })
    
    g3dView.getView().addEventListener(\'drop\', function(e) {
        // 擷取滑鼠位置模型    
        var data = g3dView.getDataAt(e);
        if(!data) return;
        // 滑鼠位置不是預置模型,直接跳過
        if(data.getDisplayName() !== \'box\') return;
        data.s(\'shape3d.opacity\', 0);
        // 放手時候設定 所有的 displayName 為 box 的節點 不可見
        array.forEach(function(data) {
            data.s(\'3d.visible\', false);
        });

        var node = new ht.Node();
        node.s(\'shape3d\', url); // 檔案袋 3D 模型位址
        node.r3([Math.PI/2, -Math.PI/2, 0]); // 旋轉檔案袋模型, 使其平放
        node.p3(data.p3());
        node.setParent(g3dView._focusData);
        node.setHost(g3dView._focusData);
    });      

檔案櫃虛化效果實作

上面我們已經實作了檔案袋拖拽至 3D 場景的效果,但是我們可以發現檔案袋模型遠小于櫃子,要将檔案袋擺放到正确的位置并不是那麼容易。是以此時我們可以将需要操作的檔案櫃放大到正中間,其它模型進行虛化處理。

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統
  // 3D 拓撲互動監聽
    g3dView.mi(function(e){
        if(e.kind === \'doubleClickData\') {
            // 輕按兩下事件
            var shape3d = e.data.s(\'shape3d\'),
                parentShape3d = e.data.getParent() && e.data.getParent().s(\'shape3d\');
            if (shape3d && shape3d.indexOf(\'檔案櫃\') > -1) {
                // 重點突出檔案櫃
                showDetail(e.data);
            }
            else if (parentShape3d && parentShape3d.indexOf(\'檔案櫃\') > -1) {
                showDetail(e.data.getParent());
            }
        }
    });

    showDetail = function(data) {
        // 儲存進入虛化狀态前 視角 與 中心點
        eyeBack = ht.Default.clone(graph3dView.getEye());
        centerBack = ht.Default.clone(graph3dView.getCenter());
    
        // 設定相機指向配置
        var opt = {};
        opt.animation = true;
        opt.ratio = 1;
        opt.direction = [1, 0.5, 0];
        opt.center = [data.getX(), 100, data.getY()];

        graph3dView.flyTo(data, opt);
        focusData = data;

        data.s(\'select.brightness\', 1);
        dataModel.each(function (d) {
            if (d === focusData || (!d.s(\'3d.selectable\') && d.getTag() !== \'wall\')
                || d.getParent() === focusData || d.getDisplayName() === \'box\') return;
            // 将拓撲中除了要操作的櫃子 與櫃子中檔案袋 以及牆外 透明度都設定為 opacity (0~1)
            
            // 儲存設定前配置, 還原用
            if (!opacityMap[d.getId()]) {
                opacityMap[d.getId()] = {
                    \'shape3d.opacity\': d.s(\'shape3d.opacity\'),
                    \'shape3d.transparent\': d.s(\'shape3d.transparent\'),
                    \'all.opacity\': d.s(\'all.opacity\'),
                    \'all.transparent\': d.s(\'all.transparent\'),
                    \'left.opacity\': d.s(\'left.opacity\'),
                    \'left.transparent\': d.s(\'left.transparent\'),
                    \'right.opacity\': d.s(\'right.opacity\'),
                    \'right.transparent\': d.s(\'right.transparent\'),
                    \'front.opacity\': d.s(\'front.opacity\'),
                    \'front.transparent\': d.s(\'front.transparent\'),
                    \'back.opacity\': d.s(\'back.opacity\'),
                    \'back.transparent\': d.s(\'back.transparent\'),
                    \'top.opacity\': d.s(\'top.opacity\'),
                    \'top.transparent\': d.s(\'top.transparent\'),
                    \'bottom.opacity\': d.s(\'bottom.opacity\'),
                    \'bottom.transparent\': d.s(\'bottom.transparent\'),
                    \'3d.selectable\': d.s(\'3d.selectable\')
                }
            }
            
            // 透明度設定為 opacity
            d.s({
                \'shape3d.opacity\': opacity,
                \'shape3d.transparent\': true,
                \'all.opacity\': opacity,
                \'all.transparent\': true,
                \'left.opacity\': opacity,
                \'left.transparent\': true,
                \'right.opacity\': opacity,
                \'right.transparent\': true,
                \'front.opacity\': opacity,
                \'front.transparent\': true,
                \'back.opacity\': opacity,
                \'back.transparent\': true,
                \'top.opacity\': opacity,
                \'top.transparent\': true,
                \'bottom.opacity\': opacity,
                \'bottom.transparent\': true,
                \'3d.selectable\': false
            });

        });
    }      

退出虛化模式,以監控 3D 拓撲的選中變化來實作

     g3dView.dm().ms(function(e) {
        var lastData = g3dView.sm().ld();
        // 判斷是否進行虛化
        if(focusData) {
            if(lastData === focusData || (lastData && lastData.getParetn() === focusData)) return;
            g3dView.setEye(eyeBack);
            g3dView.setCenter(centerBack);
            // 還原模型的原透明度
            g3dView.dm().each(function (d) {
                if (d === focusData) return;
                d.s(opacityMap[d.getId()]);
            });
            
            focusData.s(\'select.brightness\', 0.7);
            focusData = null;
            eyeBack = null;
            centerBack = null;
        }
    });      

快速查詢功能實作

在 HT 的元件中有提供快速查詢插件 QuickFinder ,此次我們就運用該插件來實作簡單的檔案編号查詢

  // 初始化 輸入框
    var textField = new ht.ui.TextField;
    textField.setIcon("imgs/search.json");
    textField.setIconPosition("left");

    // 初始化查詢器,條件:id
    var finder = new ht.QuickFinder(library.view.dm, "id");
    // 輸入框點選查詢按鈕時觸發
    textField.on(\'p:value\', function(e) {
        var dm = library.view.dm;
        var value = e.newValue;
        var datas = finder.find(value);
        // 查詢到對應的圖元時,我們将第一個結果進行選中
        if (datas && datas.size() > 0) {
            library.view.dm.sm().ss(datas.get(0));
        }
    });      
基于 WebGL 3D 的 HTML5 檔案館可視化管理系統

總結

經過以上功能的實作,一個基礎的智慧檔案管理系統就成形了。當然做為一個智慧管理系統,這些還是遠遠不夠的,例如檔案動态監控、檔案室内人員走動監控、視訊監控、溫度監控、災害報警等等子產品都是後期可以完善的地方。這裡隻是簡單地為大家提供了一個基于 HTML5 WEBGL 的 3D 解決方案。同樣原理,智能樓宇、智能機房、智能城市也可以基于此來實作。

最終效果可檢視:https://hightopo.com/demo/intelligent-archives/

基于 WebGL 3D 的 HTML5 檔案館可視化管理系統
基于 WebGL 3D 的 HTML5 檔案館可視化管理系統