基于 WebGL(ThingJS)的室内平面图 2D/3D 导航 DEMO(Part 1) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
xiangbulala
V2EX    Javascript

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

  •  
  •   xiangbulala 2019-01-05 15:17:35 +08:00 6454 次点击
    这是一个创建于 2472 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言
    利用 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.57131498969785, 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, }); }

    第 1 条附言    2019-01-08 11:24:37 +08:00
    补充一下图片:




    26 条回复    2019-01-10 17:17:48 +08:00
    Shaun42
        1
    Shaun42  
       2019-01-09 10:09:27 +08:00 via Android
    应用范围真广。
    jixia
        2
    jixia  
       2019-01-09 10:23:39 +08:00
    这个界面貌似 1:1 模模搭
    xiangbulala
        3
    xiangbulala  
    OP
       2019-01-09 10:24:39 +08:00
    @Shaun42 主要是三维可视化
    xiangbulala
        4
    xiangbulala  
    OP
       2019-01-09 11:07:12 +08:00
    @jixia 就是模模搭呀,模模搭作为 thingjs 的三维场景搭建组件


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


    全景图


    图表搭建



    供电局供电结构可视化


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

    我争取不是那么广告哈哈
    xiangbulala
        10
    xiangbulala  
    OP
       2019-01-09 11:21:54 +08:00
    @pupboss 在那个项目负责什么?
    pupboss
        11
    pupboss  
       2019-01-09 11:23:37 +08:00
    @xiangbulala 这个还是不说了,gov 部门的项目,神秘点好 hhhh
    xiangbulala
        12
    xiangbulala  
    OP
       2019-01-09 11:55:32 +08:00
    @loserwn 嘿~关注一下优锘的 ThingJS 喽~
    karlakte
        13
    karlakte  
       2019-01-09 13:11:13 +08:00
    大屏可视化啊 广告啊
    hdr01
        14
    hdr01  
       2019-01-09 13:54:35 +08:00
    我寻思也没开源啊?
    Lattez
        15
    Lattez  
       2019-01-09 13:59:28 +08:00
    让我想到我们实验室一拨人是用 Threejs 做 bim 的....
    xiangbulala
        16
    xiangbulala  
    OP
       2019-01-09 14:21:27 +08:00
    @hdr01 暂时还没这个计划...
    elevenjin
        17
    elevenjin  
       2019-01-09 14:47:11 +08:00
    这和 sketch up 有啥区别?
    xiangbulala
        18
    xiangbulala  
    OP
       2019-01-09 15:16:27 +08:00
    @elevenjin sketch up 侧重建模,thingjs 侧重的是 3D 应用和可视化管理
    比如智慧楼宇的可视化管理,腾讯微瓴
    xiangbulala
        19
    xiangbulala  
    OP
       2019-01-09 15:17:42 +08:00
    @Lattez three.js 做 bim 轻量化的厂商挺多的吧
    goodbyennn
        20
    goodbyennn  
       2019-01-09 15:31:13 +08:00
    @xiangbulala 大佬,有时间接外包么?做汽车模型展示,用 WebGl 的技术
    knight322
        21
    knight322  
       2019-01-09 16:57:00 +08:00
    @goodbyennn
    你怕是问错人了。。。不过可以联系我
    markyangd
        22
    markyangd  
       2019-01-09 19:08:15 +08:00 via iPhone
    知道了,不要再发广告了,发大段大段的代码毫无意义。
    xiangbulala
        23
    xiangbulala  
    OP
       2019-01-09 19:18:05 +08:00 via Android
    @markyangd 下次发图( ̄. ̄)
    goodbyennn
        24
    goodbyennn  
       2019-01-09 22:31:41 +08:00
    @knight322 私我联系方式?
    spaceack
        25
    spaceack  
       2019-01-10 17:12:43 +08:00
    CampusBuilder 不支持 Linux 吧?
    xiangbulala
        26
    xiangbulala  
    OP
       2019-01-10 17:17:48 +08:00
    @spaceack 不支持,不过 H5 版本编辑器快发布了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2333 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 15:53 PVG 23:53 LAX 08:53 JFK 11:53
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86