如何使用webgl(three.js)實現3D消防、3D建築消防大樓、消防數字孿生、消防可視化解決方案——第十八課(一)

来源:https://www.cnblogs.com/yeyunfei/archive/2023/03/11/17205445.html
-Advertisement-
Play Games

three.js、webgl、3D消防、智慧消防、三維消防、使用three.js(webgl)搭建智慧樓宇消防、3D園區、3D廠房、3D倉庫、設備檢測、數字孿生、物聯網3D、物業3D監控、物業基礎設施可視化運維、3d建築,3d消防,消防演習模擬,3d庫房,webGL,threejs,3d機房,bim... ...


序:

  又是很久沒出隨筆文章了,一篇文章有時候整理一天,實在是抽不出來時間。

  最近在回顧幾年前的項目時,發現這個智慧三維消防可視化項目很有回顧價值,索性就拿出來講講。

  首先,我們要知道消防里的知識,不是簡簡單單的幾個滅火器,煙感報警器這麼簡單的,消防是自有一套完整體系的,光是消防相關的產業年產值就有幾千個億。而我們普通非專業人士常見的消防設備只是消防產業中的皮毛。

  單是消防系統就可以分為很多類,常見的有消防給水系統、消火栓系統、自動噴水滅火系統、氣體滅火系統、防煙排煙系統、火災自動報警系統等等。這些系統內部的組成結構又各有不同。每個系統里就有幾十個甚至上百個不同的消防設備。比如我們常見的消防噴頭就有好幾種,各自用於不同的建築場景。

  還是閑話少序,切入正題。

前言:

  前面的課程里,有一篇文章《使用webgl(three.js)搭建一個3D智慧園區、3D建築,3D消防模擬,web版3D,bim管理系統——第四課》是介紹實現消防模擬的。本文以及後續的篇幅將系統的介紹消防可視化方案。

  這篇文章由於篇幅原因,我專門這一篇先介紹一下常見的消防系統,以及代碼框架,在後續的篇幅里我們再各個擊破,詳細介紹每個消防系統的3D實現方案。

  我們是技術類文章,這裡只能做一個簡單的常見的消防系統定義介紹:

    消防給水系統:以水為滅火劑消防撲救火災的供水系統。由水源、消防給水管網、消防水池、消防水泵及消火栓、自動噴水滅火設施等組成。

    消火栓系統:消火栓系統一般都由主泵和備用泵組成。一般按鈕啟動後,先啟動1#泵,1#泵啟動失靈,自動轉啟2#泵,只有當兩台泵都不能啟動時,控制盤上才顯示故障。消防水泵的故障,一般是指水泵電機斷電、過載及短路等

    自動噴水滅火系統:自動噴水滅火系統由灑水噴頭、報警閥組、水流報警裝置等組件,以及管道、供水設施組成,並能在發生火災時噴水的自動滅火系統。

    氣體滅火系統:氣體滅火系統主要用在不適於設置水滅火系統等其他滅火系統的環境中

    防煙排煙系統:防排煙系統,都是由送排風管道、管井、防火閥、門開關設備、送、排風機等設備組成

    火災自動報警系統:火災自動報警系統是由觸發裝置、火災報警裝置、聯動輸出裝置以及具有其它輔助功能裝置組成的

  上述系統,在我們實現3D軟體模擬過程中,程式員需要詳細知道各系統的工作原理,作用,才不會出現重大的業務性bug。(這就是程式員為啥會掉頭髮,基本在做一個系統體系時,就需要學習瞭解一遍)

  言歸正傳,我們下麵對各系統架構做一些概括性講解。

一、效果展示

 1.1、消防給水系統效果展示

 

 系統涉及各部件展示,邏輯結構展示,通過剖面視角、管網視角,全方位,多視角展示改系統的結構組成。

其功能實現的主要偽代碼如下:

首先創建系統對象,用於各系統之間的切換

$(function () {
    indexPage = new IndexPage();
    indexPage.init();
    for (var i = 1; i <= 6; i++) {
        if (window["System0" + i]) {
            window["system0" + i] = new window["System0" + i]();
            window["system0" + i].init();
        }
    }
});

切換系統事件綁定

    $(".res .sys").click(function () {
        $("#sysMainNav").hide();
        $("#sysNav1").show();
        $("#sysNav2").show();
        var systemindex = $(this).attr("data-systemIndex");
        console.log(systemindex);
       
        if (window["system0" + systemindex]) {
            window["system0" + systemindex].show();
        }
    });

主功能切換

//功能ui
IndexPage.prototype.showSystemMainNav1 = function (nav1) {
    layer.closeAll();
    $("#backToMainNav").nextAll().remove();
    if (nav1 && nav1.length > 0) {
        var sysNav1_detailhtml = "";
        $.each(nav1, function (_index, _obj) {
            sysNav1_detailhtml += '<div id="' + _obj.id + '"  class="boxbg ' + _obj.defaultState + '" onclick="if(indexPage.clickme){return false;};indexPage.clickme=true;setTimeout(function(){indexPage.clickme=false},500);' + _obj.actionStr + ';">\
               <img src= "../img/' + (_obj.defaultState == "noselect" ? "dot_unselect.png" : "dot_selected.png") + '" class="s1icontime" />\
                   <p class="timeP">' + _obj.name + '</p>\
        </div >';
        });
        $("#backToMainNav").after(sysNav1_detailhtml);
    }
}

 

 1.2、消火栓系統

 消火栓系統與消防給水系統功能類似,只是其組成部件的側重點不一樣

例如消火栓註重分室外、室內、乾式、濕式、水鶴等等

這裡我們是展示模型的視角不一樣

   modelBussiness.hideAllPLSystemDevs(200, function () {
                layer.msg("loading...", { time: 1000 });
                if (param.greatePosition) {
                    var greatePosition = param.greatePosition[_this.nav1State];
                    var camera = { x: 0, y: 0, z: 0 };
                    var target = { x: 0, y: 0, z: 0 };
                    var abloutModelNames = null;
                    var abloutModelObjs = null;
                    if (greatePosition) {
                        camera = greatePosition.camera;
                        target = greatePosition.target;
                        abloutModelNames = greatePosition.abloutModelNames;
                    }
                    if (abloutModelNames == "All") {
                        modelBussiness.showAllDevModels(1);
                    }
                    else if (abloutModelNames && abloutModelNames.length > 0) {
                        abloutModelObjs = WT3DObj.commonFunc.findObjectsByNames(abloutModelNames);
                        if (abloutModelObjs && abloutModelObjs.length > 0) {
                            $.each(abloutModelObjs, function (_index, _obj) {
                                _obj.visible = true;
                            });
                        }
                    }
                    WT3DObj.commonFunc.changeCameraPosition(camera, target, 1000, function () {
                        if (id == "s02_03_ssshs" || id == "s02_03_gsshs") {
                            if (_objs) {
                                $.each(_objs, function (_index, _obj) {
                                    if (_obj.name == "pldev_t10_1_7") {
                                        WT3DObj.commonFunc.changeObjsOpacity([_obj], 1, 0.2, 50, function () {
                                        });
                                    }
                                    if (_obj.name == "pldev_t10_1_7_inner" && id == "s02_03_gsshs") {
                                        _obj.visible = false;

                                    }

                                    if (_obj.name == "pldev_t10_1_7_inner" && id == "s02_03_ssshs") {
                                        _obj.visible = true;
                                    }
                                });
                            }

                        }
                    });
                } else {
                    console.log("數據初始化異常!沒有設置最佳位置");
                    return;
                }
            });

 

 1.3、自動噴水滅火系統

該系統註重整體運作原理,在部件中特意加了原理動畫講解

 【系統部件原理動畫舉例

 動畫實現偽代碼:

//執行動畫 遞歸調用
System02.prototype.doAnimation = function () {
    modelBussiness.showAllPLSystemDevs(50, function () {
    modelBussiness.hideAllBuildModels();
    modelBussiness.opcityDevs(function () {
        modelBussiness.changeDevsToSSMaterial();
        WT3DObj.commonFunc.changeCameraPosition({ x: -34, y: -331, z: -546 }, { x: -412, y: -260, z: 135 }, 1000, function () {
        });
        var actions = system02.nav2[2].children;
        if (actions && actions.length > 0) {
            function doaction(action_nub) {
                $("#" + actions[action_nub].id).attr("class", "nav2res navsys");
                if (action_nub > 0) {
                    $("#" + actions[action_nub - 1].id).attr("class", "nav2res navsys noseleced");
                }
                actions[action_nub].action(function () {
                    if (actions[action_nub + 1] && actions[action_nub + 1].action) {
                        doaction(action_nub + 1);
                    }
                });
            }
            doaction(0);
        }
    });
    });
}
 var animationChildren=[

                {
                    name: "發生火情",
                    id: "s01_step01",
                    greatePosition: {
                        camera: { x: -1388, y: -781, z: -309 },
                        target: { x: -2119, y: -1106, z: 873 }
                    },
                    actionStr: "",
                    action: function (callBack) {
                        modelBussiness.addFire(function () {
                            setTimeout(function () {
                                callBack();
                            }, 2000);
                        });
                    }
                },
                {
                    name: "噴淋動作",
                    id: "s01_step02",
                    greatePosition: {
                        camera: { x: -1388, y: -781, z: -309 },
                        target: { x: -2119, y: -1106, z: 873 }
                    },
                    actionStr: "",
                    action: function (callBack) {
                        console.log("執行2");
                        //找到噴淋
                        var pls = WT3DObj.commonFunc.findObjectsByNames(["pldev_penling_1_1_28", "pldev_penling_1_1_28_sp_1", "pldev_penling_1_1_28_sp_2", "pldev_penling_1_1_28_sp_3"]);
                        WT3DObj.commonFunc.flashObjs(pls, "flashPL", 0xff0000, 10, 200, 0);
                        setTimeout(function () {
                            var pl = pls[0];
                            pl.children[1].visible = false;
                            pl.children[3].visible = false;
                            //噴淋裂開
                            var pls1 = pls[1];
                            var p1x = pls1.position.x;
                            var p1z = pls1.position.z;
                            var pls2 = pls[2];
                            var pls3 = pls[3];
                            pls1.oldpostion = { x: pls1.position.x, y: pls1.position.y, z: pls1.position.z };
                            new TWEEN.Tween(pls1.position).to({
                                x: p1x + 100 * (Math.random() < 0.5 ? -5 * Math.random() : 3 * Math.random()),
                                y: -2000,
                                z: p1z + 100 * (Math.random() < 0.5 ? -5 * Math.random() : 3 * Math.random())
                            }, 8000).start();
                            new TWEEN.Tween(pls2.position).to({
                                x: p1x + 100 * (Math.random() < 0.5 ? -5 * Math.random() : 3 * Math.random()),
                                y: -2000,
                                z: p1z + 100 * (Math.random() < 0.5 ? -5 * Math.random() : 3 * Math.random())
                            }, 8000).start();
                            new TWEEN.Tween(pls3.position).to({
                                x: p1x + 100 * (Math.random() < 0.5 ? -5 * Math.random() : 3 * Math.random()),
                                y: -2000,
                                z: p1z + 100 * (Math.random() < 0.5 ? -5 * Math.random() : 3 * Math.random())
                            }, 8000).start();
                            //開始噴水
                            modelBussiness.addWater(
                                function () {
                                    setTimeout(function () {
                                        callBack();
                                    }, 1000);
                                }
                            );

                        }, 2000);
                    }
                },
                ......]

 1.4、氣體滅火系統

 在氣體系統中,實現方式又有點不一樣,前面幾個系統都是代碼模型,該系統使用了大量的載入模型,如座椅板凳等

該系統也是主要展現系統部件跟工作動畫原理

動畫中採用了大量的定時器,閉包,回調,遞歸等等,這裡特別註意記憶體有效回收,否者瀏覽器可能會隨時崩潰

例如如下代碼:

  var a_messagePanel_1126 = WT3DObj.commonFunc.findObject("a_messagePanel_1126");
    a_messagePanel_1126.position.x=1499.804;
    a_messagePanel_1126.position.y = 474.389;
    a_messagePanel_1126.position.z = -74.822;
    moveXH(a_messagePanel_1126, { x: 2008.767, y: 474.389, z: -74.822, t: 0 }, 2000);
    setTimeout(function () {
        moveXH(a_messagePanel_1126, { x: 2007.926, y: 478.648, z: -451.129, t: 2000 }, 2000);
        setTimeout(function () {
            moveXH(a_messagePanel_1126, { x: -657.755, y: 478.648, z: -451.129, t: 2000 }, 2000);
            WT3DObj.commonFunc.changeCameraPosition({ x: -295.23352627790484, y: 445.15353495337854, z: -140.38158326269246 }, { x: -798.2079071244784, y: 270.3977749099737, z: -511.7589163393606 }, 10, function () {


            });
            setTimeout(function () {
                moveXH(a_messagePanel_1126, { x: -657.755, y: 478.648, z: -303.566, t: 2000 }, 2000);
                setTimeout(function () {
                    moveXH(a_messagePanel_1126, { x: -657.755, y: 339.858, z: -303.566, t: 2000 }, 2000);
                    setTimeout(function () {
                        a_messagePanel_1126.visible = false;
                        moveXH(a_messagePanel_1126, { x: -662.270, y: 315.038, z: -339.977, t: 2000 }, 2000);
                        setTimeout(function () {
                            a_messagePanel_1126.visible = true;
                            moveXH(a_messagePanel_1126, { x: -662.270, y: 465.038, z: -339.977, t: 2000 }, 2000);
                            setTimeout(function () {
                                moveXH(a_messagePanel_1126, { x: -662.270, y: 465.038, z: -719.977, t: 2000 }, 2000);

                                setTimeout(function () {
                                    WT3DObj.commonFunc.changeCameraPosition({ x: 1672.1492964146757, y: 437.22502365828495, z: -946.6467804045902 }, { x: 1393.4110369255911, y: 391.9499762093484, z: -843.1414359356829 }, 1000, function () {

                                    });
                                    moveXH(a_messagePanel_1126, { x: 1433, y: 465.038, z: -719.847, t: 2000 }, 2000);
                                    setTimeout(function () {
                                        moveXH(a_messagePanel_1126, { x: 1433, y: 465.038, z: -739.847, t: 2000 }, 2000);

                                    setTimeout(function () {
                                        moveXH(a_messagePanel_1126, { x: 1429.452, y: 382.109, z: -739.847, t: 2000 }, 2000);
                                        setTimeout(function () {
                                            sgbjq2(callBack);
                                        }, 2000);
                                    }, 2000);
                                    }, 2000);
                                }, 2000);
                            }, 2000);

                        }, 2000);

                    }, 2000);

                }, 2000);

            }, 2000);

        }, 2000);

    }, 2000);
/*
關閉送(排)風機及送(排)風閥門
停止通風和空調系統及關閉該防護區的電動防火閥
關閉防護區的門窗

*/

/*
向驅動氣瓶電磁閥發送開啟信號,可設≤30s 的延遲噴射

*/
function djsdz(callBack) {
    
    var dev = WT3DObj.commonFunc.findObjectsByNames([
                   "dev_ledFont_1",
    ])[0];
    for (var i = 30; i >=0; i--) {
        (function (a) {
            setTimeout(function () {
                if (a <10) {
                    a = "0"+a;
                }
                dev.freshData(a);
            },1000 * (30 - a));
        })(i);
       
    }
    setTimeout(function () {
        callBack();
    },31 * 1000);
}

 

 1.5、防煙排煙系統

 防排煙系統也是加了動畫的形式,充分展現了其工作原理與組成部件

 action: function (callBack) {
                        //剖面圖
                        $.each(system07.allModels, function (_index, _obj) {
                            if (_obj.hasoldPosition) {
                                _obj.position.y = _obj.hasoldPosition.y ;
                            }
                            _obj.visible = true;
                        });
                        $.each(system07.foreModels, function (_index, _obj) {
                            if (_obj.hasoldPosition) {
                                _obj.position.y = _obj.hasoldPosition.y + 10000;
                            } else {
                                _obj.hasoldPosition = { y: _obj.position.y };
                                _obj.position.y = _obj.hasoldPosition.y + 10000;
                            }
                            _obj.visible = false;
                        });
                        //發生火情
                        system07.stepName = "發生火情!";
                        layer.msg("</br><font style='color:#ffffff;font-size:20px;'>發生火情!</font></br>");
                        WT3DObj.commonFunc.changeCameraPosition({ x: 6120.260855819656, y: 1344.6126089802272, z: 10903.874792293966 },  { x: 6292.0698848787415, y: 106.7257770257646, z: 4388.448120618271 }, 1000, function () {
                            addLines();
                            addFire();
                            addFYSFK();
                            setTimeout(function () {
                                WT3DObj.commonFunc.changeCameraPosition({ x: 5416.2974093433795, y: 1500.4126878089987, z: 7749.928368473556 }, { x: 5474.770344242846, y: 899.4381166888209, z: 4216.286318511336 }, 2000, function () {
                                    callBack();
                                });
                            }, 2000);
                        });
                    }
                },
System07.prototype.doAnimationFlag = false;
System07.prototype.showNav2Action = function (index, id) {
    var _this = this;
    modelBussiness.removeSingleShowDevs();
    console.log(id);
    if ((_this.nav1State == "s07_05" || _this.nav1State == "s07_06") && _this.doAnimationFlag) {
        layer.log("正在執行動畫");
        return;
    }
    $("#" + _this.nav2State).attr("class", "nav2res navsys noseleced");
    $("#" + id).attr("class", "nav2res navsys");
    _this.nav2State = id;
    var param = _this.getNav2Param(index, id);
    if (!param) {
        console.log("數據初始化異常!");
        return;
    }
    layer.closeAll();
    this.playVoice(index, id);
    if (param.dataId && id != "s04_02_gsgd") {
        modelBussiness.showDevList(param.dataId);
    }
    function flashFunc() {

        if (param && param.flashNames && param.flashNames.length > 0) {
            var fnames = [];
            $.each(param.flashNames, function (_findex, _fobj) {
                var _n = _fobj;
                if (_fobj.indexOf("_children_") > 0) {
                    _n = _fobj.split("_children_")[0];
                }
                fnames.push(_n);
            });
            _objs = WT3DObj.commonFunc.findObjectsByNames(fnames);
            if (param.flashNames[0] == "All") {
                _objs = modelBussiness.getAllPLSystemDevs();
            }
            setTimeout(function () {
                WT3DObj.commonFunc.flashObjs(_objs, "flashPL", 0x00ff00, 8, 150, 0);
            }, 1000);
        }
    }
    flashFunc();
    switch (_this.nav1State) {
        //全景
        case "s07_01":
        //剖面
        case "s07_02":
        //管網
        case "s07_04":
        case "s07_03":
            if (param.greatePosition) {
                var greatePosition = param.greatePosition[_this.nav1State];
                var camera = { x: 0, y: 0, z: 0 };
                var target = { x: 0, y: 0, z: 0 };
                if (greatePosition) {
                    camera = greatePosition.camera;
                    target = greatePosition.target;
                }
                WT3DObj.commonFunc.changeCameraPosition(camera, target, 1000, function () { });
            } else {
                console.log("數據初始化異常!沒有設置最佳位置");
                return;
            }
            break;
        //動畫
        case "s07_06":
        case "s07_05":
            {
                //param.action(function () {
                //    system07.stepName = null;
                //});
            }
            break;
    }

 

 1.6、火災自動報警系統

1.6.1、地上部分排煙動畫演練 部分錄屏

 

 1.6.2、地下部分自動報警動畫演練 部分錄屏

 部分代碼如下:

  function move(id) {
        var dv = document.getElementById(id);
        var x = 0;
        var y = 0;
        var l = 0;
        var t = 0;
        var isDown = false;
        //滑鼠按下事件
        dv.onmousedown = function (e) {
            //獲取x坐標和y坐標
            x = e.clientX;
            y = e.clientY;

            //獲取左部和頂部的偏移量
            l = dv.offsetLeft;
            t = dv.offsetTop;
            //開關打開
            isDown = true;
            //設置樣式  
            dv.style.cursor = 'move';
        }
        //滑鼠移動
        window.onmousemove = function (e) {
            if (isDown == false) {
                return;
            }
            //獲取x和y
            var nx = e.clientX;
            var ny = e.clientY;
            //計算移動後的左偏移量和頂部的偏移量
            var nl = nx - (x - l);
            var nt = ny - (y - t);

            dv.style.left = nl + 'px';
            dv.style.top = nt + 'px';
            layer.closeAll();
        }
        //滑鼠抬起事件
        dv.onmouseup = function () {
            //開關關閉
            isDown = false;
            dv.style.cursor = 'default';
        }
    }
    move("ccAnimationgif");

 

二、實現邏輯

 2.1、模型創建

  模型創建講究的是充分理解業務需求,以及把控性能跟網路的資源情況,採用代碼模型與載入模型靈活配合。

  代碼模型,更好的節約了帶寬與記憶體資源,提升了用戶體驗。載入模型,降低了開發門檻,提升了效率,但其沒有代碼模型靈活可控

  各自案例如下:

  代碼模型:

[{"show":true,"uuid":"","name":"cube2_6","objType":"cube2","length":200,"width":200,"height":200,"x":0,"y":200,"z":0,"style":{"skinColor":16777215,"skin":{"skin_up":{"skinColor":16777215,"imgurl":"../../img/3dImg/rack_inside.jpg","materialType":"basic","side":1,"opacity":1},"skin_down":{"skinColor":16777215},"skin_fore":{"skinColor":16777215},"skin_behind":{"skinColor":16777215},"skin_left":{"skinColor":16777215},"skin_right":{"skinColor":16777215}}},"showSortNub":6}]
View Code

  載入模型:

{"name":"twaver_idc_jiazi_7","objType":"objmodel","position":{"x":0,"y":0,"z":0},"scale":{"x":1,"y":1,"z":1},"visible":true,"rotation":[{"direction":"x","degree":0}],"filePath":"../../js/msj3D/sourse/models/jiazi/","mtlFileName":"jiazi.mtl","objFileName":"jiazi.obj","mtlIsPublic":false,"showSortNub":7}
View Code

 

2.2、場景創建  

  場景搭建通過把各個模型組合而成業務所需要的場景

  搭建場景時需要考慮業務的邏輯關係,什麼時候要用,什麼時候需要釋放,哪些模型屬於一個場景,哪些模型屬於邏輯打開的場景

  例如在邏輯控制中,如何有效的隱藏顯示模型:

//隱藏所有設備
ModelBussiness.prototype.hideAllDevModels = function (timelong, callBackFunc) {
    var _this = this;
    var devModels = _this.getAllDevModels();
    if (devModels && devModels.length > 0) {
        WT3DObj.commonFunc.changeObjsOpacity(devModels, 1, 0.01, timelong ? timelong : 1000, function () {
            $.each(devModels, function (_index, _obj) {
                _obj.visible = false;
            });
            WT3DObj.commonFunc.changeObjsOpacity(devModels, 0.9, 1, 1, function () {
                if (callBackFunc) {
                    callBackFunc();
                }
            });
        });
    }
}
ModelBussiness.prototype.showAllDevModels = function (timelong, callBackFunc) {
    var _this = this;
    var devModels = _this.getAllDevModels();
    if (devModels && devModels.length > 0) {
        $.each(devModels, function (_index, _obj) {
            _obj.visible = true;
        });
        WT3DObj.commonFunc.changeObjsOpacity(devModels, 0.5,1, timelong ? timelong : 1000, function () {
            if (callBackFunc) {
                callBackFunc();
            }
        });
    }
}

 

2.3、場景切換

  場景切換,除了在場景內部通過事件切換的方式,還有就是大場景切換

  對於大場景切換,通常採用兩種方式,一種時改變路由的方式,一種是釋放當前資源,載入新資源

  這裡我們採用對象化載入的方式

  初始化對象:

$(function () {
indexPage = new IndexPage();
indexPage.init();
for (var i = 1; i <= 6; i++) {
if (window["System0" + i]) {
window["system0" + i] = new window["System0" + i]();
window["system0" + i].init();
}
}
});
//系統1:室內外消防給水系統
function System01() {
}
//初始化
System01.prototype.init = function () {
    
}
//顯示
System01.prototype.show = function () {
    console.log("顯示室內外消防給水系統");
    this.loadVoice();
    this.initUI();
    modelBussiness.loadDevModels(1, function () {
        modelBussiness.hideAllInsideBoxs();
    });
}
System01.prototype.initUI = function () {
    //主功能
    this.nav1 = [
        {
            defaultState: "",
            name: "全景視角",
            id: "s01_01",
            actionStr: "system01.showNavSystem('s01_01')"
        },
        {
            defaultState: "noselect",
            name: "剖面視角",
            id: "s01_02",
            actionStr: "system01.showNavSystem('s01_02')"
        },
        {
            defaultState: "noselect",
            name: "管網視角",
            id: "s01_03",
            actionStr: "system01.showNavSystem('s01_03')"
        },
        {
            defaultState: "noselect",
            name: "系統部件",
            id: "s01_04",
            actionStr: "system01.showNavSystem('s01_04')"

        }
    ]
    //子功能
    ....
    /*
    消防水泵
    消防供水管道
    */
    indexPage.showSystemMainNav1(this.nav1);
    this.nav1State = "s01_01";
    indexPage.showSystemMainNav2(this.nav2[0]);
    this.nav2State = "";

}

 

2.4、動畫模擬

   動畫模擬,這裡採用了配置載入的方式,不用每一個動畫去寫邏輯代碼,因為涉及到動畫比較多,但動畫都是基於時間線的,所以我們把需要執行的步驟放到配置裡面,再通過統一的方法去調用

  例如動畫列表配置如下:

  {
            name: "排煙動畫",
            children: [
                
                {
                    name: "發生火情",
                    id: "s07_step01",
                    greatePosition: {
                        camera: { x: 6120.260855819656, y: 1344.6126089802272, z: 10903.874792293966 },
                        target: { x: 743.2076296596372, y: 901.5537889282617, z: -467.5814262976444 }
                    },
                    actionStr: "system07.showNav2Action(2,'s07_step01')",
                    action: function (callBack) {
                        //剖面圖
                        $.each(system07.allModels, function (_index, _obj) {
                            if (_obj.hasoldPosition) {
                                _obj.position.y = _obj.hasoldPosition.y ;
                            }
                            _obj.visible = true;
                        });
                        $.each(system07.foreModels, function (_index, _obj) {
                            if (_obj.hasoldPosition) {
                                _obj.position.y = _obj.hasoldPosition.y + 10000;
                            } else {
                                _obj.hasoldPosition = { y: _obj.position.y };
                                _obj.position.y = _obj.hasoldPosition.y + 10000;
                            }
                            _obj.visible = false;
                        });
                        //發生火情
                       //do something...
                    }
                },
                {

                    name: "感煙探測器",
                    id: "s07_step02_1",
                    greatePosition: {
                        camera: { x: -1388, y: -781, z: -309 },
                        target: { x: -2119, y: -1106, z: 873 }
                    },
                    actionStr: "system07.showNav2Action(2,'s07_step02_1')",
                    action: function (callBack) {
                //do something...
                    }
                },
                {

                    name: "煙感信號發送",
                    id: "s07_step02_2",
                    greatePosition: {
                        camera: { x: -1388, y: -781, z: -309 },
                        target: { x: -2119, y: -1106, z: 873 }
                    },
                    actionStr: "system07.showNav2Action(2,'s07_step02_2')",
                    action: function (callBack) {
                       //do something...
                         
                    }
                },
              ....
                {
                    name: "動畫結束",
                    id: "s07_step11",
                    greatePosition: {
                        camera: { x: 1737.3999068753242, y: 2415.4782632988126, z: -333.6159257900231 },
                        target: { x: 1239.420815260611, y: 1011.0884298164777, z: 2597.9725494779173 }
                    },
                    actionStr: "system07.showNav2Action(2,'s07_step11')",
                    action: function (callBack) {
                        
                        
                        //刪除船船

                        //刪除所有ani開頭的模型

                        //停止旋轉

                        //縮小擋煙垂壁

                    }
                }
            ]
        },

執行動畫如下:

 

//執行動畫
System07.prototype.doAnimation = 
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Shell命令-常用操作2 1 vim 用法: vim filename 說明:用於打開指定的文件 三個模式 進入文件後,是normal模式 normal模式:在此模式下可以通過i進入編輯模式,通過:或/進入命令模式; 游標移動:因為linux下不支持游標跟隨滑鼠點擊,所以提供了很多游標快速移動的命 ...
  • 公眾號:MCNU雲原生,文章首發地,歡迎微信搜索關註,更多乾貨,第一時間掌握! @ 一、PostgreSQL是什麼? PostgreSQL是一種開源的關係型資料庫管理系統,也被稱為Postgres。它最初由加拿大電腦科學家Michael Stonebraker在1986年創建,其目標是創建一個具有 ...
  • 前言 我08年畢業,大學跟著老師培訓班學習的C#,那時(2003-2010)它很是時髦,畢業後也就從事了winform窗體應用程式開發。慢慢的web網站興起,就轉到asp.net開發,再到後來就上了另一艘大船(java),前端app混合開發。近三年從事web站點運維,從linux基礎+docker, ...
  • SQL實踐1 藉著學校的資料庫實驗,來對之前學習的SQL語言進行實踐和總結。 實驗環境: macOS 13.2 (22D49) mysql Ver 8.0.32 for macos13.0 on arm64 (Homebrew) DataGrip 2022.3.3 一. DataGrip連接本地My ...
  • 本文已經收錄到Github倉庫,該倉庫包含電腦基礎、Java基礎、多線程、JVM、資料庫、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分散式、微服務、設計模式、架構、校招社招分享等核心知識點,歡迎star~ Github地址:https://github.c ...
  • Redis(REmote DIctionary Service)是一個開源的鍵值對資料庫伺服器。 Redis 更準確的描述是一個數據結構伺服器。Redis 的這種特殊性質讓它在開發人員中很受歡迎。 ...
  • 前言 今天我們來解密下init.ts中的代碼內容,並結合 vue 生命周期來分析下 vue 的初始化; GitHub github page 內容 init.ts import config from '../config' import { initProxy } from './proxy' i ...
  • 好家伙,本篇為《JS高級程式設計》第二五章“瀏覽器存儲”學習筆記 我們先來講個故事 一個“薅羊毛”的故事 (qq.com) 概括一下,就是 有個人通過網路平臺非法購買了大量“cookie”數據。 突破平臺封控,冒用他人新用戶身份,非法騙取新用戶優惠券。 拿著優惠券低價購入商品,隨後轉賣並從中賺取差價 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...