前言

三维场景时常需要一个导航标识,用来确定场景所处的方位。

一般有两种表现形式:指南针、小方盒(方位魔方)。

参考一下百度百科中的 maya 界面,可以看到右上角有一个标识方位的小盒子,说的就是它:

Hightopo 的 HT for Web 产品可以很方便地构造轻量化的 3D 可视化场景,在 web 端 我们可以利用 HT 2D 引擎 和 3D 渲染引擎 来实现这个功能,搭建一个简易的类 maya 操作界面。

预览地址: https://www.hightopo.com/demo/compass-and-directionbox/

界面简介及效果预览

在这个界面里面我们用到了一个二维场景和两个三维场景,具体效果如下:

功能实现

先来描述一下页面布局:

指南针 通过在 ht.graph.GraphView 中给一个图元设置一个事先绘制好的图标来实现,只需把它放在图纸的左上角(即下图中的位置 1)即可。

方位魔方 通过在一个小场景 (ht.graph3d.Graph3dView)中放置一个魔方 obj 模型来实现,然后把这个小场景放置在图纸的右上角(即下图中的位置 2) 即可。

主三维场景(ht.graph3d.Graph3dView)作为背景放置在整个二维页面的下方(即下图中的位置 3)。

代码示例:

const g3d = new ht.graph3d.Graph3dView();

g3d.setOriginAxisVisible(true);

g3d.setGridVisible(true);

g3d.addToDOM();

const g2d = new ht.graph.GraphView();

g2d.deserialize('displays/test.json', json => {

g2d.addToDOM(g3d.getView());

});

位置关系:

指南针同步

先约定一下方位,我们将 Z 轴的负半轴的方向作为北方,Z 轴正半轴作为南方,X 轴的正半轴作为东方,X 轴的负半轴作为西方。

由于 指南针 的目的是用于指示鸟瞰图中的方位,所以与 Y 轴并没有什么关系,我们可以将整个计算过程放在二维空间中进行。

代码示例:

const eye = this.g3d.getEye();

const center = this.g3d.getCenter();

const v = new ht.Math.Vector2(eye[0], eye[2]);

const v2 = new ht.Math.Vector2(center[0], center[2]);

const angle = v.sub(v2).angle() - Math.PI / 2;

compass.setRotation(-angle);

compass.a('angle', angle);

compass.a('angle2', angle);

在这段代码中,我们用eye(相机) 和center (观测点)来构建两个二维向量 (ht.Math.Vector2),舍弃掉 Y 轴上的分量。

利用向量减法,求得由 center 指向 eye 的向量并存入变量 v 中,利用 angle() 方法可以获取到当前向量与 x 正半轴 (即正东方向)的夹角(弧度制),为什么要减去 Math.PI / 2 呢,因为我们计算求得的是与 x 轴的夹角,而指南针的正方向(北方)是对应着 z 轴的负半轴。

求得了旋转角度后,通过 setRotation() 方法我们可以设置 指南针 图元的旋转角度,为什么要取一个负值(- angle)?因为当视线逆时针转动的时候,坐标轴 和 指南针 相对于人眼是沿反方向运动的,也就是顺时针旋转。

利用 HT 2D引擎提供的 数据绑定 的功能,轮盘图标 和 角度图标 的旋转角度可以通过给 compass 这个节点设置属性值来实时动态改变。

每一次视线发生改变都需要进行如上的计算和设置,我们可以通过给三维场景组件增加一个属性监听器来实现:

graph3dView.addPropertyChangeListener(e=>{

if(e.property === 'eye' || e.property === 'center'){

changeCompass();

//...

}

});

图例参考:

方位魔方同步

先约定一下方位,X 正半轴为右,负半轴为左; Y 正半轴为顶,负半轴为底;Z 正半轴为前,负半轴为后。

方位魔方不同于指南针,它用于呈现三维空间中的视线方位。

与此同时,它也是一个可以交互的方位操纵杆,可以方便快捷的将当前视角变为顶视图、侧视图等。

视线改变触发魔方变换

代码示例:

graph3dView.addPropertyChangeListener(e => {

if (e.property === 'eye') {

const newValue = e.newValue;

const vEye = new ht.Math.Vector3(newValue[0], newValue[1], newValue[2]).normalize();

graph3dView2.setEye([300 * vEye.x, 300 * vEye.y, 300 * vEye.z]);

}

});

在上述代码中我们通过监听主三维场景(graph3dView) 中eye属性的变化来动态改变小场景(graph3dView2) 中的 eye 的位置, 来达到联动的效果。

其中,e.newValue 会获取到场景视点改变后的值,我们用这个值构建一个三维向量(ht.Math.Vector3)并调用 normalize() 方法进行归一化,这样可以使得任何角度、位置求得的距离都保持一致。

将求得的分量乘以 300 的原因在于这个距离观测小方块不大不小刚合适,当然也可以根据需要改成别的值。

效果示例:

点击魔方改变场景视角

要想实现点击魔方来改变主场景中的视线,需要一个非常关键的信息,那就是鼠标究竟点击了小魔方的哪一个面。

在这里我们需要用到一个求交点的方法:graph3dView.intersectObject(event, data),该方法会返回一个对象,该对象用于描述点击的位置信息, 其中 world属性用来表示点击位置的世界坐标。

代码示例:

graph3dView2.addInteractorListener(event => {

if (event.kind === 'clickData') {

const obj = graph3dView2.intersectObject(event.event, event.data);

if(obj) {

const world = obj.world;

//...

}

}

});

拿到了这个描述点击位置的 world 属性我们就可以比较轻松地算出点击了哪个面,因为我们的小方块是放置在原点处,并且它是规则的六面体,这两个关键信息决定了无论点击它的哪一个面,所点击的那个面它所对应的轴的分量的值一定会大于它在另外两个轴的分量,因此我们可以简单的判断三分量中哪个值较大就能确定视线更靠近哪个轴,然后通过判断分量的正负号来判断是在正半轴还是负半轴。

判断了出了点击的哪个面之后,只需要在两个三维场景中分别设置各自视点(eye) 的位置即可。

代码示例:

const world = obj.world;

const x = world.x;

const y = world.y;

const z = world.z;

if (Math.abs(x) - Math.abs(y) > 0 && Math.abs(x) - Math.abs(z) > 0) {

if (x > 0) {

graph3dView2.setEye([300, 0, 0]);

graph3dView.setEye([this._distance, 0, 0]);

graph3dView2.setCenter([0, 0, 0]);

this._g3d.setCenter([0, 0, 0]);

} else {

graph3dView2.setEye([-300, 0, 0]);

graph3dView.setEye([-this._distance, 0, 0]);

graph3dView2.setCenter([0, 0, 0]);

graph3dView.setCenter([0, 0, 0]);

}

} else if (Math.abs(y) - Math.abs(x) > 0 && Math.abs(y) - Math.abs(z) > 0) {

//...

}

其中,this._distance 是用来描述主场景中视线与原点的距离,可根据需要来调整,300 与之前的描述一致,是小场景中一个比较合适的视角位置,也可以根据需要调整。

最后我们还需要处理一下小方块点击变色的问题(这也不见得是个问题,视需求而定),可以在点击事件监听器的最后做如下设置:

1 const sm = graph3dView2.dm().getSelectionModel();

2 sm.setSelection(null);

点击魔方各个面效果演示:

总结

直观的方位指示在室内定位、GIS、车站、机场等诸多场景中有着广泛的应用,利用 HT 提供的二三维引擎可以轻松地实现。

web 3D 有无限的想象空间,有着非常丰富的数据呈现方式,更有着诸多让人眼前一亮的可视化效果,等着我们去将这些数据呈现方式在各个行业中落地,HT 在这方面做了大量的探索和尝试,例如这个好玩儿的太阳系监控系统:https://www.hightopo.com/demo/solar-system/

2019 我们也更新了数百个工业互联网 2D/3D 可视化案例集,在这里你能发现许多新奇的实例,也能发掘出不一样的工业互联网:《分享数百个 HT 工业互联网 2D 3D 可视化应用案例之 2019 篇》,更多行业应用实例可以参考官网案例链接:

https://www.hightopo.com/demo...

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[分享 HT 实用技巧:实现指南针和 3D 魔方导航]http://www.zyiz.net/tech/detail-141212.html

html5 怎么插指南针,分享 HT 实用技巧:实现指南针和 3D 魔方导航相关推荐

  1. html5应用转换教程,20佳惊艳的HTML5应用程序示例分享_html5教程技巧

    1-HTML5 Canvas Collage 基于HTML5 Canvas开发的拼贴应用,每个图层都可以按不同的方式进行改变,例如移动.缩放.旋转.透明度.阴影等,还可以调整层叠顺序. 2-Full ...

  2. iOS系统预览文件但不分享的实用技巧 (iOS10, QLPreviewController)

    苹果系统的文件预览能力对于很多app来说是必要的,但其提供的UI相关api并不是可以定制的,比如需要定制toolbar, navigationbar的情况,直接使用QLPreviewControlle ...

  3. Excel数据抓取、制作、分享,实用技巧大揭秘!

    数据抓取和处理是现代信息化社会中必不可少的重要环节.为了更好地利用和分析各种数据,我们需要采用各种手段来进行数据的抓取和处理.本文将从以下八个方面详细介绍如何进行数据抓取.制作.分享和连接Excel. ...

  4. 视频教程-PPT软件基础实用技巧标准视频教程入门-Office/WPS

    PPT软件基础实用技巧标准视频教程入门 3D数字互动领域的技术研发.以用户为核心,以市场为导向,提升用户体验,提高数字内容品质,着力打造数字内容国际一流品牌.目前拥有多个自主知识产权的软件项目:手机V ...

  5. 快过年了,分享 25 个 JS 实用技巧送给大家吧

    本文主要介绍一些JS中用到的小技巧,可以在日常Coding中提升幸福度,将不定期更新~ 类型强制转换 1.1 string强制转换为数字 可以用 *1来转化为数字(实际上是调用 .valueOf方法) ...

  6. ps4jump大乱斗服务器维护,Jump大乱斗新人实用技巧分享 新手注意事项介绍

    Jump大乱斗新人实用技巧分享 新手注意事项介绍 2019-02-15 11:30:23来源:jumpforce吧/媚鬼丶编辑:云曼衍评论(0) <Jump大乱斗>已经于今天正式和玩家们见 ...

  7. Edge浏览器兼容性设置,实用技巧,分享给你(2023新版)

    ​Edge浏览器兼容性设置是一项非常重要且实用的功能技巧,可以帮助小伙伴更好地访问那些需要特定浏览器设置或版本的网站和应用程序.在本文中,小编将简要介绍如何使用Edge浏览器兼容性设置,以便各位小伙伴 ...

  8. 各代码三元运算符表达式实用技巧分享

    各代码三元运算符表达式实用技巧分享 三目运算符介绍 大多数编程语言三目运算符使用语法 1.Java语言 2.Js语言 3.Lua语言 三目运算符介绍 什么是三元运算符? 三元运算符又称为"三 ...

  9. rust矿洞绳子怎么爬下_腐蚀RUST实用技巧分享 教你在游戏中横着走

    腐蚀RUST实用技巧分享,游戏中有一些机制和玩法超出玩家们的想象.接下来就给大家带来腐蚀RUST一些实用技巧介绍,都是一些非常实用的技巧,一起来看看吧. [一]无伤高出下坠 众所周知的方法是怼着墙冲刺 ...

最新文章

  1. 讨论:有多少项目是因为程序的原因而失败的
  2. Hadoop 02_初学必知
  3. 从Java连接到Cassandra
  4. twisted mysql_Twisted MySQL adbapi返回字典
  5. 知识付费网站php源码,原创在线教育知识付费类源码只要50元
  6. MyEclipse中使用Junit插件进行单元测试
  7. python3闭包通俗解释_python通俗解说闭包
  8. 2021-08-08索引在小数据量的时候用处不大,但在大数据的时候十分明显
  9. AR Camera开发记录(三) -- 替换人脸贴图
  10. 电脑一拖二的学习方法
  11. python统计pdf字数代码_Python基本数据统计.pdf
  12. PPT的一键操作 原来这么神奇
  13. SAR图像聚焦质量评价插件
  14. Assembler如何把跳转汇编变成机器码的(四)
  15. 【JS继承】什么是JS继承?
  16. 记录解决流氓软件无法删除-被资源管理器打开以及被xx程序打开导致无法删除
  17. 金山wps c++开发二面总结
  18. django orm查询经纬度最近距离的数据
  19. 电脑上的回收站无法清空
  20. 多网聚合路由系统打通“融媒体”5G丝绸之路

热门文章

  1. Php设计模式之【适配器模式 Adapter Pattern】
  2. Java学习笔记---Lambda表达式及Stream流Api
  3. 工业生产中的“主动刹车”,是怎么实现的?
  4. Windows 2008 R2、2012 R2 磁盘扩容、新加磁盘
  5. 曼尼托巴大学计算机科学世界排名,曼尼托巴大学世界排名多少
  6. 亚马逊商城评论数据分析与可视化(KNN预测评分,绘制云图)
  7. vue视频,vue视频下载
  8. python调用usb设备_用Python与USB设备通信
  9. win7和ubuntu关闭防火墙方法
  10. 近似概率编程文献综述