基於WebGL架構的3D視覺化平臺—三維裝置管理(ThingJS實現樓宇裝置管理3D視覺化)

ThingJS發表於2018-12-14

國內高層建築不斷興建,它的特點是高度高、層數多、體量大。面積可達幾萬平方米到幾十萬平方米。這些建築都是一個個龐然大物,高高的聳立在地面上,這是它的外觀,而隨之帶來的內部的建築裝置也是大量的。為了提高裝置利用率,合理地使用能源,加強對建築裝置狀態的監視等,自然地就提出了樓宇自動化控制系統。下面我們將用ThingJS平臺來模擬一個裝置管理系統。

第一步,利用CampusBuilder搭建模擬場景。CampusBuilder的模型庫有各種各樣的模型,使我們搭建出的場景更逼真。使用CampusBuilde建立層級,之後再給層級加外立面就出現了當前的效果。詳情移步:CampusBuilder3D場景製作工具

先看結果:演示地址

第二步,建立Equipment類,這裡建立。switchControl方法主要一個完成一個計時器的功能來模擬裝置警報。

class Equipment extends THING.Thing {
    constructor(app, name, obj, url) {
        super(app);
        this.name = name;
        this.obj = obj;
        this.url = url;
        this.interval = null;
        this.localPosition = [Math.floor(Math.random() * 7), 2.9, Math.floor(Math.random() * 7)];
    }
    createSelf() {
        app.create({
            type: `Equipment`,
            name: this.name,
            url: this.url,
            parent: this.obj,
            localPosition: this.localPosition,
            angle: 0
        });
    }
    switchControl(ev) {
        var flag;
        var equipment = app.query(this.name)[0];
        app.level.change(equipment);
        if (ev) {
            this.interval = setInterval(function () {
                if (flag) {
                    equipment.style.color = `#FF0000`;
                    flag = false;
                } else {
                    flag = true;
                    equipment.style.color = ``;
                }
            }, 500);
            console.log(this.interval + "檢視是否建立了定時器");
        } else {
            console.log(this.interval);
            clearInterval(this.interval);
            if (equipment.style.color == `#FF0000`)
                equipment.style.color = ``;
        }
    }
}
THING.factory.registerClass(`Equipment`, Equipment);

  第三步,建立攝像機皮膚,煙感報警皮膚以及控制裝置的開關,這裡簡單調整一下皮膚位置之後會增加兩個建立裝置的按鈕。

//建立主皮膚
var panel1 = new THING.widget.Panel({
    titleText: `攝像機列表`,
    closeIcon: false, // 是否有關閉按鈕
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
});
panel1.position = [80, 0];

var panel2 = new THING.widget.Panel({
    titleText: `煙感報警列表`,
    closeIcon: false, // 是否有關閉按鈕
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
});
panel2.position = [80, 320];

// 建立任意物件
var dataObj1 = {
    open1: false,
    open2: false,
    open3: false,
    open4: false,
}
var dataObj2 = {
    open5: false,
    open6: false,
    open7: false,
    open8: false,
};

// 動態繫結物體
var open1 = panel1.addBoolean(dataObj1, `open1`).caption(`裝置01`);
var open2 = panel1.addBoolean(dataObj1, `open2`).caption(`裝置02`);
var open3 = panel1.addBoolean(dataObj1, `open3`).caption(`裝置03`);
var open4 = panel1.addBoolean(dataObj1, `open4`).caption(`裝置04`);
var open5 = panel2.addBoolean(dataObj2, `open5`).caption(`裝置01`);
var open6 = panel2.addBoolean(dataObj2, `open6`).caption(`裝置02`);
var open7 = panel2.addBoolean(dataObj2, `open7`).caption(`裝置03`);
var open8 = panel2.addBoolean(dataObj2, `open8`).caption(`裝置04`);

  第四步,開啟場景層級切換,建立攝像機和煙感報警器各四個,建立一個數字標識index和儲存equipment物件的陣列equipmentGroup。

//建立equipment物件陣列,以及陣列標識
var equipmentGroup = [];
var index = 0;

app.on(`load`, function (ev) {

    app.level.change(ev.campus);

    for (var i = 0; i < 8; i++) {
        var type = null;
        if (i < 4) {
            type = `http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/`;
        } else {
            type = `http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/`;
        }
        var equipment = new Equipment(app, `equipment` + index++, app.query(`floor` + (Math.floor(Math.random() * 5) + 1))[0], type);
        equipment.createSelf();
        equipmentGroup.push(equipment);
    }
});

  第五步,為每個裝置對應的建立控制開關。

open1.on(`change`, function (ev) {
        equipmentGroup[0].switchControl(ev);
    });
    open2.on(`change`, function (ev) {
        equipmentGroup[1].switchControl(ev);
    });
    open3.on(`change`, function (ev) {
        equipmentGroup[2].switchControl(ev);
    });
    open4.on(`change`, function (ev) {
        equipmentGroup[3].switchControl(ev);
    });
    open5.on(`change`, function (ev) {
        equipmentGroup[4].switchControl(ev);
    });
    open6.on(`change`, function (ev) {
        equipmentGroup[5].switchControl(ev);
    });
    open7.on(`change`, function (ev) {
        equipmentGroup[6].switchControl(ev);
    });
    open8.on(`change`, function (ev) {
        equipmentGroup[7].switchControl(ev);
    });

  最後一步,建立兩個按鈕來控制建立裝置。

new THING.widget.Button(`建立煙感報警`, function () {
    var type = `http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/`;
    var equipment = new Equipment(app, `equipment` + index++, app.query(`floor` + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});

new THING.widget.Button(`建立攝像頭`, function () {
    var type = `http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/`;
    var equipment = new Equipment(app, `equipment` + index++, app.query(`floor` + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});

  

在編寫過程還是走了不少彎路的,最主要的就是計時器的解除安裝問題,最初的版本寫來寫去發現不能控制警報的關閉,後來才 發現計時器沒有解除安裝,警報不但不會關閉而且閃動的頻率越來越快。更改之後建立了Equipment這個類來控制所有裝置,通過建立這個類的物件給他賦id,父物體,模型地址。這裡控制器在開關被觸發的時候建立一個新的計時器並賦給的這個物件,再次觸發時清除這個計時器,警報的動畫就關閉了。演示地址

最後附上完整程式碼:

/**
 * 說明:建立App,url為場景地址(可選)
 */
var app = new THING.App({
    url: "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/CampusBuilder20181126134710",    // 場景地址
    "skyBox": "BlueSky"
});

//建立主皮膚
var panel1 = new THING.widget.Panel({
    titleText: `裝置列表`,
    closeIcon: false, // 是否有關閉按鈕
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
    titleImage: `https://www.thingjs.com/static/images/example/icon.png`
});
panel1.position = [80, 0];

var panel2 = new THING.widget.Panel({
    titleText: `裝置列表`,
    closeIcon: false, // 是否有關閉按鈕
    dragable: true,
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
    titleImage: `https://www.thingjs.com/static/images/example/icon.png`
});
panel2.position = [80, 320];
// 建立任意物件
var dataObj1 = {
    open1: false,
    open2: false,
    open3: false,
    open4: false,
}
var dataObj2 = {
    open5: false,
    open6: false,
    open7: false,
    open8: false,
};

// 動態繫結物體
var open1 = panel1.addBoolean(dataObj1, `open1`).caption(`裝置01`);
var open2 = panel1.addBoolean(dataObj1, `open2`).caption(`裝置02`);
var open3 = panel1.addBoolean(dataObj1, `open3`).caption(`裝置03`);
var open4 = panel1.addBoolean(dataObj1, `open4`).caption(`裝置04`);
var open5 = panel2.addBoolean(dataObj2, `open5`).caption(`裝置01`);
var open6 = panel2.addBoolean(dataObj2, `open6`).caption(`裝置02`);
var open7 = panel2.addBoolean(dataObj2, `open7`).caption(`裝置03`);
var open8 = panel2.addBoolean(dataObj2, `open8`).caption(`裝置04`);

new THING.widget.Button(`建立煙感報警`, function () {
    var type = `http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/`;
    var equipment = new Equipment(app, `equipment` + index++, app.query(`floor` + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});

new THING.widget.Button(`建立攝像頭`, function () {
    var type = `http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/`;
    var equipment = new Equipment(app, `equipment` + index++, app.query(`floor` + (Math.floor(Math.random() * 5) + 1))[0], type,);
    equipment.createSelf();
    equipmentGroup.push(equipment);
    app.level.change(app.query(equipment.name)[0]);
});
//建立equipment物件陣列,以及陣列標識
var equipmentGroup = [];
var index = 0;


app.on(`load`, function (ev) {

    app.level.change(ev.campus);

    for (var i = 0; i < 8; i++) {
        var type = null;
        if (i < 4) {
            type = `http://model.3dmomoda.cn/models/62A8A75C75044E6AB3D8463FA0CB67AF/0/gltf/`;
        } else {
            type = `http://model.3dmomoda.cn/models/641A9B800DE5431E8C84DC290F8EFDE6/0/gltf/`;
        }
        var equipment = new Equipment(app, `equipment` + index++, app.query(`floor` + (Math.floor(Math.random() * 5) + 1))[0], type);
        equipment.createSelf();
        equipmentGroup.push(equipment);
    }

    open1.on(`change`, function (ev) {
        equipmentGroup[0].switchControl(ev);
    });
    open2.on(`change`, function (ev) {
        equipmentGroup[1].switchControl(ev);
    });
    open3.on(`change`, function (ev) {
        equipmentGroup[2].switchControl(ev);
    });
    open4.on(`change`, function (ev) {
        equipmentGroup[3].switchControl(ev);
    });
    open5.on(`change`, function (ev) {
        equipmentGroup[4].switchControl(ev);
    });
    open6.on(`change`, function (ev) {
        equipmentGroup[5].switchControl(ev);
    });
    open7.on(`change`, function (ev) {
        equipmentGroup[6].switchControl(ev);
    });
    open8.on(`change`, function (ev) {
        equipmentGroup[7].switchControl(ev);
    });

});

class Equipment extends THING.Thing {
    constructor(app, name, obj, url) {
        super(app);
        this.name = name;
        this.obj = obj;
        this.url = url;
        this.interval = null;
    }
    createSelf() {
        app.create({
            type: `Equipment`,
            name: this.name,
            url: this.url,
            parent: this.obj,
            localPosition: [Math.floor(Math.random() * 7), 2.9, Math.floor(Math.random() * 7)],
            angle: 0
        });
    }
    switchControl(ev) {
        var flag;
        var equipment = app.query(this.name)[0];
        app.level.change(equipment);
        if (ev) {
            this.interval = setInterval(function () {
                if (flag) {
                    equipment.style.color = `#FF0000`;
                    flag = false;
                } else {
                    flag = true;
                    equipment.style.color = ``;
                }
            }, 500);
            console.log(this.interval + "檢視是否建立了定時器");
        } else {
            console.log(this.interval);
            clearInterval(this.interval);
            if (equipment.style.color == `#FF0000`)
                equipment.style.color = ``;
        }
    }
}

THING.factory.registerClass(`Equipment`, Equipment);

  


相關文章