基于 WebGL(ThingJS)的室内平面图 2D/3D 导航 DEMO(Part 1)

2019-01-05 15:17:35 +08:00
 xiangbulala

前言
利用 CampusBuilder 来搭建自己的虚拟世界过程有这样一个问题:如何快速聚焦到虚拟场景的某一位置。当然我们可以创建几个按钮对应查找我们需要去的位置(参照物)并聚焦,但是按钮并不是很炫酷也不能很好的反馈给我们一些信息。接下来我们就用平面导航图来解决这一问题。

实现
第一步,使用 CampusBuilder 搭建模拟场景,CampusBuilder 操作简单,分分钟就可以上手。这里为每一个房间都创建一个小球作为视点参照物体并勾选预览时隐藏,这样不会对我们的场景造成影响,也便于我们聚焦到指定房间。注意:要将我们每个房间中的设备框选之后组合在一起,为下一阶段的做准备。

 

第二步,把我们编辑好的场景加载到 ThingJS 中。

//加载场景代码
var app = new THING.App({
	// 场景地址
	"url": "http://www.thingjs.com/./uploads/wechat/S2Vyd2lu/scene/Campus04",
});
//场景相关
//************************************************************************************/
app.on('load', function () {
    app.camera.flyTo({
        'position': [36.357131498969785, 61.953024217074265, 69.12160670337104],
        'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544],
        'time': 2000,
    });
});

第三步,为平面图创建一块面板,并调整一下面板的位置以及大小。
图片下载地址:
链接:https://pan.baidu.com/s/1gmNjIj2ekbw1rO3MoujHqQ 提取码:i0c1

//面板相关
//************************************************************************************/
var panel = new THING.widget.Panel({
    closeIcon: false,
    dragable: false, 
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
});
panel.width = 600;
panel.position = [0, 200];
var dataObj = {
    iframe: ''
};
var iframe = panel.addIframe(dataObj, 'iframe').caption('').setHeight("290px");

第四步,编写 iframe 页。写完记得将这个页面和图片上传到页面资源,资源 => 页面资源 => 按钮(上传) 。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
      	.total_image {
        	margin : 20px;
        }
        .total_image img{
            cursor: pointer;
            transition: all 0.6s;
            width: 50px;
        }
        .total_image img:hover{
            transform: scale(1.5);
            position:relative;
            z-index:100;
        }
    </style>
</head>
<body>
<div class="total_image" style="width: 500px;height: 280px;background-size: 100% auto">
    <img class="model_imag" src="发电室 1.jpg" style="float: left;display: block;width: 85px;height: 84px" 
			onclick="onClick('PowerGenerationGroup_01','viewPoint_1')" >
&lt;img class="model_imag" src="发电室 2.jpg" style="float: left;display: block;width: 78px;height: 84px" 
		onclick="onClick('PowerGenerationGroup_02','viewPoint_2')" &gt;
          
&lt;img class="model_imag" src="发电室 3.jpg" style="float: left;display: block;width:170px;height: 84px" 
		onclick="onClick('PowerGenerationGroup_03','viewPoint_3')" &gt;
          
&lt;img class="model_imag" src="发电室 4.jpg" style="float: left;display: block;width:167px;height: 84px" 
		onclick="onClick('PowerGenerationGroup_04','viewPoint_4')" &gt;
          
&lt;div style="display: block;float: left;width: 100px;height: 145px;background-color:white"&gt;
    &lt;img class="model_imag" src="办公室 1.jpg" style="float: left;display: block;width:100px;height: 60px" 
		onclick="onClick('Office','viewPoint_5')" &gt;
    &lt;img class="model_imag" src="返回.png" style="float: left;display: block;width:100px;height: 80px" onclick="initViewPoint()"&gt;
&lt;/div&gt;

&lt;img class="model_imag" src="发电室 5.jpg" style="float: right;display: block;width:123px" 
		onclick="onClick('PowerGenerationGroup_05','viewPoint_8')" &gt; 
          
&lt;img class="model_imag" src="会议室 1.jpg" style="float: left;display: block;width: 138px;height: 145px"  alt="" 
		onclick="onClick('BoardRoom_01','viewPoint_6')"&gt;
          
&lt;img class="model_imag" src="会议室 2.jpg" style="float: left;display: block;width: 138px;height: 145px"  alt="" 
		onclick="onClick('BoardRoom_02','viewPoint_7')" &gt; 

</div>

<script> function onClick(viewPoint,target){ window.parent.onClick(viewPoint,target); } function initViewPoint(){ window.parent.initViewPoint(); } </script> </body> </html>

第五步,完成 onClick()和 initViewPoint()方法。

//事件相关
//************************************************************************************/
var currentModule = null;

//点击事件 function onClick(targetObj, viewPoint) { currentModule = app.query(targetObj)[0]; currentModule.position = [0, 0, 0]; currentModule.style.opacity = 1; app.camera.flyTo({ 'object': app.query(viewPoint)[0], 'offset': [0, 13, 7], 'time': 1000, complete: function () { currentModule.brothers.style.opacity = 0.3; } }); } //返回事件 function initViewPoint() { currentModule.brothers.style.opacity = 1; currentModule = null; app.camera.flyTo({ 'position': [36.357131498969785, 61.953024217074265, 69.12160670337104], 'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544], 'time': 1000, }); }

小结
第一部分我们主要完成了 iframe 与我们的 3D 场景的简单交互,这里也没有做什么特效只是做了一个点击事件。这里值得一提的是 currentModule 这个全局变量,开始我没有创建这个变量只是将我当前点击的物体 obj.style.opacity = 1;obj.brothers.style.opacity = 0.3, 但是执行 initViewPoint(){app.query(’.Thing’).style.opacity=1}无法将场景的 opacity 属性还原(自己可以试一下,或者有解决方案留言)。第二部分我会给 iframe 页加上鼠标悬停事件让 iframe 页的 img 标签和我们场景中的 obj 一起动起来!

完整代码,可以粘到 ThingJS 网站在线开发环境运行http://www.thingjs.com/guide/?m=sample

	//加载场景代码
var app = new THING.App({
	// 场景地址
	"url": "http://www.thingjs.com/./uploads/wechat/S2Vyd2lu/scene/Campus04",
});
//场景相关
//************************************************************************************/
app.on('load', function () {
    app.camera.flyTo({
        'position': [36.357131498969785, 61.953024217074265, 69.12160670337104],
        'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544],
        'time': 2000,
    });
});
//面板相关
//************************************************************************************/
var panel = new THING.widget.Panel({
    closeIcon: false,
    dragable: false, 
    retractable: true,
    opacity: 0.9,
    hasTitle: true,
});
panel.width = 600;
panel.position = [0, 200];
var dataObj = {
    iframe: '/uploads/wechat/S2Vyd2lu/file/平面图导航 /ifram.html'
};
var iframe = panel.addIframe(dataObj, 'iframe').caption('').setHeight("290px");

//事件相关 //************************************************************************************/ var currentModule = null;

//点击事件 function onClick(targetObj, viewPoint) { currentModule = app.query(targetObj)[0]; currentModule.position = [0, 0, 0]; currentModule.style.opacity = 1; app.camera.flyTo({ 'object': app.query(viewPoint)[0], 'offset': [0, 13, 7], 'time': 1000, complete: function () { currentModule.brothers.style.opacity = 0.3; } }); } //返回事件 function initViewPoint() { currentModule.brothers.style.opacity = 1; currentModule = null; app.camera.flyTo({ 'position': [36.357131498969785, 61.953024217074265, 69.12160670337104], 'target': [-1.3316924326803257, -4.9370371421622625, 33.619521849828544], 'time': 1000, }); }

 

5697 次点击
所在节点    JavaScript
26 条回复
Shaun42
2019-01-09 10:09:27 +08:00
应用范围真广。
jixia
2019-01-09 10:23:39 +08:00
这个界面貌似 1:1 模模搭
xiangbulala
2019-01-09 10:24:39 +08:00
@Shaun42 主要是三维可视化
xiangbulala
2019-01-09 11:07:12 +08:00
@jixia 就是模模搭呀,模模搭作为 thingjs 的三维场景搭建组件


此外还提供了城市组件,图表组件,全景图和模型库


全景图


图表搭建



供电局供电结构可视化


蔬菜大棚
pupboss
2019-01-09 11:11:28 +08:00
兄弟你这广告发的有点频繁了啊
xiangbulala
2019-01-09 11:16:49 +08:00
@pupboss 哈哈我就置顶一下反正 V 站只能置顶一条...
loserwn
2019-01-09 11:18:03 +08:00
看界面这么眼熟。。仔细看是优锘。做 DCIM 可视化还是挺好看的。
pupboss
2019-01-09 11:19:11 +08:00
@xiangbulala 我去,,刚点开你主页,发现了不得了的东西,gbic,新加坡建筑局,我曾经也在这个项目
xiangbulala
2019-01-09 11:21:24 +08:00
@pupboss 点开我主页...看到更多的广告....

我争取不是那么广告哈哈
xiangbulala
2019-01-09 11:21:54 +08:00
@pupboss 在那个项目负责什么?
pupboss
2019-01-09 11:23:37 +08:00
@xiangbulala 这个还是不说了,gov 部门的项目,神秘点好 hhhh
xiangbulala
2019-01-09 11:55:32 +08:00
@loserwn 嘿~关注一下优锘的 ThingJS 喽~
karlakte
2019-01-09 13:11:13 +08:00
大屏可视化啊 广告啊
hdr01
2019-01-09 13:54:35 +08:00
我寻思也没开源啊?
Lattez
2019-01-09 13:59:28 +08:00
让我想到我们实验室一拨人是用 Threejs 做 bim 的....
xiangbulala
2019-01-09 14:21:27 +08:00
@hdr01 暂时还没这个计划...
elevenjin
2019-01-09 14:47:11 +08:00
这和 sketch up 有啥区别?
xiangbulala
2019-01-09 15:16:27 +08:00
@elevenjin sketch up 侧重建模,thingjs 侧重的是 3D 应用和可视化管理
比如智慧楼宇的可视化管理,腾讯微瓴
xiangbulala
2019-01-09 15:17:42 +08:00
@Lattez three.js 做 bim 轻量化的厂商挺多的吧
goodbyennn
2019-01-09 15:31:13 +08:00
@xiangbulala 大佬,有时间接外包么?做汽车模型展示,用 WebGl 的技术

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/524152

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX