今天找到了 HT 的官网里的 Demo 网站( http://www.hightopo.com/demos/index.html ),看的我眼花缭乱,应接不暇。 并且 HT 的用户手册,将例子和文档无缝融合一体,小小 10 来兆开发包竟然包含了四十五份手册,数百个活生生的 HTML5 例子,还没体验过的朋友赶忙来看一看,这回可玩嗨了!html
对于 HT 初学者,面对这一堆数百个涵括通用组件、网络拓扑图组件、3D 组件、矢量图形、各类编辑器等等五法八门的 HTML5 例子盛宴,每每无从下手。为此,老郑我打算为像我同样喜欢这方面的新手朋友多写几篇这样的博客,慢慢的给你们讲述各类各样的愈来愈多的有趣的小功能!node
( https://hightopo.com/demo/CabinetAnimat/ )网络
HT 提供了基于 WebGL 的 3D 技术的图形组件 ht.graph3d.Graph3dView,WebGL 基于 OpenGL ES 2.0 图形接口,所以 WebGL 属于底层的图形 API 接口,二次开发仍是有很高的门槛,HT 的 Graph3dView 组件经过对 WebGL 底层技术的封装,与 HT 其余组件同样,基于 HT 统一的 DataModel 数据模型来驱动图形显示,极大下降了 3D 图形技术开发的门槛。同时 HT 提供了强大的彻底基于 HTML5 技术 3D 图形建模设计器,用户无需编码便可快速可视化搭建各类 3D 场景,能够说 HT 的 3D 开发模式彻底打破了传统 3D 开发模式,绝大部分应用再也不须要依赖精通 3ds Max 或 Maya 的专业 3D 设计师来建模,也不须要整合 Unity3d 等引擎作图形渲染,HT 一站式的提供了从建模到渲染,包括和 2D 组件呈现和数据融合的一站式解决方案。编辑器
我本次讲解的就是这个 3D 的界面,因此咱们首先要建立 3D 渲染引擎组件,可视化呈现数据模型的三维环境场景。ide
var dm = new ht.DataModel() var g3d = new ht.graph3d.Graph3dView(dm)
咱们还要设置眼睛(或Camera)所在位置以及中心点(目标)的位置,格式均为 [x, y, z] 。函数
g3d.setEye([-376, 270, 896])
g3d.setCenter([-16, 118, -186])
这里给你们说一下,可参考 3D 手册( http://www.hightopo.com/guide/guide/core/3d/ht-3d-guide.html )。如上图所示,透视投影最终显示到屏幕上的内容只有截头锥体 ( View Frustum ) 部分的内容, 所以 Graph3dView 提供了 eye ,center , up ,far ,near ,fovy 和 aspect 参数来控制截头锥体的具体范围:oop
而后咱们再给它加上一些选中效果。Graph3dView 中被选中的图元会显示为较暗的状态,变暗系数是由图元 style 的 brightness 和 select.brightness 属性决定,select.brightness 属性默认值为 0.7,最终返回值大于 1 变亮,小于 1 变暗,等于 1 或为空则不变化。Graph3dView#getBrightness 函数控制最终图元亮度,所以也能够经过重载覆盖该函数自定义选中图元亮度。学习
g3d.getBrightness = function (data) { if (data.s('isFocused')) { return 0.7; } return null; };
lastFocusData = null; g3d.getView().addEventListener('mousemove', function (e) { // 传入逻辑坐标点或者交互 event 事件参数,返回当前点下的图元 var data = g3d.getDataAt(e); if (data !== lastFocusData) { if (lastFocusData) { astFocusData.s('isFocused', false); } if (data) { data.s('isFocused', true); } astFocusData = data; } });
接下来咱们要为这些零件设置吸附:动画
dm.getDataByTag('机柜').setHost(dm.getDataByTag('地板')) dm.getDataByTag('设备').setHost(dm.getDataByTag('机柜')) dm.getDataByTag('门').setHost(dm.getDataByTag('机柜'))
...
吸附功能对于设计有层次关系的模型很是方便,例如设备面板吸附上设备机框,设备端口吸附上设备面板,这样从机框 - 面板 - 端口的层次关系吸附,使得用户拖动总体机框时全部这个层次下的图元都会跟随移动。对于 3D 的场景下,吸附的概念更进一步延伸,当机框在三维空间进行任意位置偏移以及任意角度旋转时,全部吸附的相关图元都会正确的跟随平移,并作出相应位置对应的旋转,以达到总体设备各个图形部分保持物理相对位置一致。简单来讲就是当图元吸附上宿主图元时,宿主移动或旋转时会带动全部吸附者。网站
由于我这里是有 6 个设备,我要把每个都给一个属性值来记录变化的状态一下子用到:
dm.getDataByTag('门').a('open', false) for (var i = 1; i < 7; i++) { dm.getDataByTag('设备' + i).a('open', false) }
上一篇关于 SCADA 组态电机的随笔里面我们已经用到过动画,这回让咱们经过事件监听在双击它的时候来为其加上动画效果:
// 监听事件 g3d.mi(function (event) { if (event.kind === 'doubleClickData') { var tag = event.data.getTag() if (tag === '门') { if (anim) { anim.stop(true) } //获取旋转角度 var oldAngles = event.data.getRotation(), angles = (open ? 2 : -2) //启动动画 anim = ht.Default.startAnim({ action : function(t) { event.data.setRotation(oldAngles + t * angles) }, }) open = !open } //检测字符串是否以指定的前缀开始 else if (tag.startsWith('设备')) { //设备动画函数 animation(event.data) } }
}
设备动画的函数在这里:
function animation(data) { //设置每一个设备依次的变化参数 var v for (var i = 1; i < 7; i++) { if (tag === '设备'+ i) { v= i / 2 }
} if (data.anim) { data.anim.stop(true) data.anim = null } var open = data.a('open'), p3 = data.p3(), s3 = data.s3() if (open) { data.anim = ht.Default.startAnim({ action : function(t) { data.p3(p3[0], p3[1], p3[2] + t * -s3[2] * v) } }) data.a('open', false) } else { data.anim = ht.Default.startAnim({ action : function(t) { data.p3(p3[0], p3[1], p3[2] + t * s3[2] * v) } }) data.a('open', true) } }
这里面有一些简写跟大伙儿说下。好比 mi 是增长交互事件监听器,addInteractorListener 的缩写,另外 event 格式有:
同时还有 3D 的一些:
建议熟记经常使用函数简写可提升编码效率,可参考入门手册中函数简写( http://www.hightopo.com/guide/guide/core/beginners/ht-beginners-guide.html )。最后别忘记 g3d.addToDOM() 呦!嘿嘿~~~
这个小 demo 就说到这里吧,我会不按期的写一些技术随笔,既帮助本身整理知识,也可以跟你们一块儿学习,咱们由浅至深,按部就班。但愿看了个人文章能得大家带来帮助,同时也但愿你们能多多支持和鼓励!