示例讲解

这章节我们将讲解一些快速应用的案例,把往期的重要知识点和项目中常见的需求场景联系起来。

拾取和选择

关于 Pick 和 选择 的讲解,我们在前文已经讲述过,本章不在做过多赘述。

物体对象监控

物体面板显示监控

在 3D 的某些应用需求中,当选中某个物体时,需要展示该物体的详细信息,我们可以创建一个物体面板,来展示这些数据。

有如下几步即可实现让物体面板显示监控:

  1. query 获取物体对象集合;
  2. 对物体集合注册单击事件;
  3. 点击选中的物体 加入Selection中;
  4. 通过Select DeSelect事件 对物体做相应的操作;
  5. 如果是接口数据 可通过Ajax或WebSocket进行请求、对接;
  6. 创建物体面板 双向绑定数据;

示例效果如下图所示:

批量显示监控面板

在某些 3D 可视化应用场景中,需要显示一批物体的某些重要指标,如何实现多个对象批量显示这些数据呢?

我们通过 UIAnchor ,将相应的数据展示面板作为孩子连接到每个对象上即可。

示例效果如下图所示:

动态加载场景

关于动态创建组合场景的讲解,我们在前文已经讲述过,本章不在做过多赘述。

实现思路如下图所示:

视频中代码实现过程的具体迭代版本如下:

版本1如下:

 var app = new THING.App({
"url": "https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%8A%A8%E6%80%81%E5%B1%82%E7%BA%A7%E5%A4%96%E7%AB%8B%E9%9D%A2",
    "skyBox": "BlueSky",
});

// 主场景加载完后 删掉楼层
app.on('load', function (ev) {
    // 进入层级切换
    app.level.change(ev.campus);

    console.log('卸载园区建筑下的默认楼层');
    // 园区加载完成后,将园区中建筑下的楼层删除(Floor)
    for (var i = 0; i < ev.buildings.length; i++) {
        ev.buildings[i].floors.destroy();
    }

});

var url = 'https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%95%86%E4%B8%9AE%E6%A5%BC%E5%B1%82%E7%BA%A7';


// 设置进入建筑事件
app.on(THING.EventType.EnterLevel, '.Building', function (ev) {

    var buildingMain = ev.object;

    console.log('动态加载');
    // 动态创建园区
    var campusTmp = app.create({
        type: 'Campus',
        // 动态创建园区的url
        url: url,
        // 在回调中,将动态创建的园区和园区下的建筑删除 只保留楼层 并添加到相应的建筑中
        complete: function () {
            var buildingTmp = campusTmp.buildings[0];
            //遍历楼层  挂接到当前进入的建筑身上
            buildingTmp.floors.forEach(function (floor) {
                //将每层Floor作为孩子 挂接到 主建筑上
                buildingMain.add({
                    object: floor,
                    // 设置相对坐标,楼层相对于建筑的位置保持一致
                    localPosition: floor.localPosition
                });
            })
            // 楼层添加后,删除园区以及内部的园区建筑
            buildingTmp.destroy();
            campusTmp.destroy();


            console.log('=== 加载完成!===');
        }
    });

}, '进入建筑创建楼层'); 

版本2如下:

var app = new THING.App({
    "url": "https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%8A%A8%E6%80%81%E5%B1%82%E7%BA%A7%E5%A4%96%E7%AB%8B%E9%9D%A2",
    "skyBox": "BlueSky",
});


// 主场景加载完后 删掉楼层 
app.on('load', function (ev) {
    // 进入层级切换
    app.level.change(ev.campus);

    console.log('卸载园区建筑下的默认楼层');
    // 园区加载完成后,将园区中建筑下的楼层删除(Floor)
    for (var i = 0; i < ev.buildings.length; i++) {
        ev.buildings[i].floors.destroy();
    }

});

var url = 'https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%95%86%E4%B8%9AE%E6%A5%BC%E5%B1%82%E7%BA%A7';


// 设置进入建筑事件
app.on(THING.EventType.EnterLevel, '.Building', function (ev) {
    console.log('=== 进入了我的事件 === ');
    var buildingMain = ev.object;

    if (buildingMain._isAlreadyBuildedFloors) {
        console.log('=== 建筑已加载!=== ');
        return;
    }
    // 动态创建园区
    var campusTmp = app.create({
        type: 'Campus',
        // 动态创建园区的url
        url: url,
        // 在回调中,将动态创建的园区和园区下的建筑删除 只保留楼层 并添加到相应的建筑中
        complete: function () {
            var buildingTmp = campusTmp.buildings[0];
            //遍历楼层  挂接到当前进入的建筑身上
            buildingTmp.floors.forEach(function (floor) {
                buildingMain.add({
                    object: floor,
                    // 设置相对坐标,楼层相对于建筑的位置保持一致
                    localPosition: floor.localPosition
                });
            })
            // 楼层添加后,删除园区以及内部的园区建筑
            buildingTmp.destroy();
            campusTmp.destroy();

            buildingMain._isAlreadyBuildedFloors = true;
            console.log('=== 加载完成!===');
        }
    });

}, '进入建筑创建楼层'); 

版本3如下:

var app = new THING.App({
    "url": "https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%8A%A8%E6%80%81%E5%B1%82%E7%BA%A7%E5%A4%96%E7%AB%8B%E9%9D%A2",
    "skyBox": "BlueSky",
});


// 主场景加载完后 删掉楼层
app.on('load', function (ev) {
    // 进入层级切换
    app.level.change(ev.campus);

    console.log('卸载园区建筑下的默认楼层');
    // 园区加载完成后,将园区中建筑下的楼层删除(Floor)
    for (var i = 0; i < ev.buildings.length; i++) {
        ev.buildings[i].floors.destroy();
    }

});

var url = 'https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%95%86%E4%B8%9AE%E6%A5%BC%E5%B1%82%E7%BA%A7';


// 设置进入建筑事件
app.on(THING.EventType.EnterLevel, '.Building', function (ev) {

    var buildingMain = ev.object;

    if (buildingMain._isAlreadyBuildedFloors) {
        console.log('=== 建筑已加载!=== ');
        return;
    }


    //  停止进入物体层级的默认飞行行为
    app.pauseEvent(THING.EventType.EnterLevel, '.Building', THING.EventTag.LevelFly);

    // 动态创建园区
    var campusTmp = app.create({
        type: 'Campus',
        // 动态创建园区的url
        url: url,
        // 在回调中,将动态创建的园区和园区下的建筑删除 只保留楼层 并添加到相应的建筑中
        complete: function () {
            var buildingTmp = campusTmp.buildings[0];
            //遍历楼层  挂接到当前进入的建筑身上
            buildingTmp.floors.forEach(function (floor) {
                buildingMain.add({
                    object: floor,
                    // 设置相对坐标,楼层相对于建筑的位置保持一致
                    localPosition: floor.localPosition
                });
            })
            // 楼层添加后,删除园区以及内部的园区建筑
            buildingTmp.destroy();
            campusTmp.destroy();

            app.resumeEvent(THING.EventType.EnterLevel, '.Building', THING.EventTag.LevelFly);

            buildingMain._isAlreadyBuildedFloors = true;
            console.log('=== 加载完成!===');
        }
    });

    // 提升事件响应的优先级
}, '进入建筑创建楼层',51); 

版本4如下:

var app = new THING.App({
"url": "https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%8A%A8%E6%80%81%E5%B1%82%E7%BA%A7%E5%A4%96%E7%AB%8B%E9%9D%A2",
"skyBox": "BlueSky",
});


// 主场景加载完后 删掉楼层
app.on('load', function (ev) {
// 进入层级切换
app.level.change(ev.campus);

console.log('卸载园区建筑下的默认楼层');
// 园区加载完成后,将园区中建筑下的楼层删除(Floor)
for (var i = 0; i < ev.buildings.length; i++) {
    ev.buildings[i].floors.destroy();
}

});

var url = 'https://www.thingjs.com/./uploads/wechat/oLX7p0wh7Ct3Y4sowypU5zinmUKY/scene/%E5%95%86%E4%B8%9AE%E6%A5%BC%E5%B1%82%E7%BA%A7';


// 设置进入建筑事件
app.on(THING.EventType.EnterLevel, '.Building', function (ev) {

var buildingMain = ev.object;

if (buildingMain._isAlreadyBuildedFloors) {
    console.log('=== 建筑已加载!=== ');
    return;
}


//  停止进入物体层级的默认飞行行为
app.pauseEvent(THING.EventType.EnterLevel, '.Building', THING.EventTag.LevelFly);

// 动态创建园区
var campusTmp = app.create({
    type: 'Campus',
    // 动态创建园区的url
    url: url,
    // 在回调中,将动态创建的园区和园区下的建筑删除 只保留楼层 并添加到相应的建筑中
    complete: function () {
        var buildingTmp = campusTmp.buildings[0];
        //遍历楼层  挂接到当前进入的建筑身上
        buildingTmp.floors.forEach(function (floor) {
            buildingMain.add({
                object: floor,
                // 设置相对坐标,楼层相对于建筑的位置保持一致
                localPosition: floor.localPosition
            });
        })
        // 楼层添加后,删除园区以及内部的园区建筑
        buildingTmp.destroy();
        campusTmp.destroy();

        app.resumeEvent(THING.EventType.EnterLevel, '.Building', THING.EventTag.LevelFly);

        // 触发层级进入事件前 在该帧内 暂停自定义的 '进入建筑创建楼层' 响应
        app.pauseEventInFrame(THING.EventType.EnterLevel,".Building",'进入建筑创建楼层');
        
        // 楼层加载完成后的建筑 触发层级进入事件
        buildingMain.trigger(THING.EventType.EnterLevel,ev);

        buildingMain._isAlreadyBuildedFloors = true;
        console.log('=== 加载完成!===');
    }
});

}, '进入建筑创建楼层',51); 

相对关系与坐标转换

相对关系

之前的教程中已经讲解过了,当创建对象,管理对象时,我们可以设置该物体的父物体。

指定了对象的父物体后,那么该对象的位移、旋转、缩放以及显示隐藏,默认都跟随父物体的变化而变化。

如果要让子对象不继承父物体的位移、旋转、缩放,可分别设置相应的 inheritPosition 、inheritAngles 、inheritScale 值为 false 实现。

坐标转换

之前的教程中已经讲解过了坐标转换,本章不在做多余赘述。

为了让大家更容易理解与使用相对关系与坐标转化,我们新增了一个 示例。

动态加载管理对象

对于一些有摆放规律或者有位置信息的管理对象(比如书柜里的书、楼层里的烟雾感应器、消防喷淋器),我们可以动态的请求数据来进行批量创建。在这种应用场景下创建管理对象时,建议设置对象的父物体、使用相对坐标,以更方便的进行对象的管理和控制。

在线咨询
QQ交流群
微信公众号