前言
物联网 ( IoT ), 简单的理解就是物体之间通过互联网进行链接. 世界上的万事万物, 都可以通过数据的改变进行智能化管理. ioT 的兴起在医疗行业中具有拯救生命的潜在作用.
不断的收集用户信息并且实时的进行诊断, 所以未来 iot 肯定在医疗行业的应用会呈覆盖性. 下面是我最近做的一个医疗物流系统, 用来观察医疗物流过程.
ht 官网链接: http://www.hightopo.com/cn-index.html
demo 链接: https://www.hightopo.com/demo/pivas/
https://www.hightopo.com/demo/flight-monitor/
实现过程
增加光源
整个原场景其实是非常暗的, 所以需要使用灯光的效果照亮整个场景, 使其接近真实世界的场景.
我们看下对比.
light 的一些属性:
type 代表灯光的类型
color 代表灯光的颜色
intensity 代表灯光的强度 (1 是最大值)
range 代表范围
- addLight() {
- const skyBox = this.dm.getDataByTag('skyBox')
- // 限制视野在天空球之内
- this.gv.setSkyBox(skyBox)
- const light = new ht.Light()
- const lightSource = this.dm.getDataByTag('sunlight').p3()
- const config = {
- 'light.type': 'point',
- 'light.color': 'white',
- 'light.intensity': 0.3,
- 'light.range': 10000
- }
- light.s(config)
- light.p3(lightSource)this.dm.add(light)
- }
看向物体
看到左下角的一个小窗口, 其实是另一个 3d 场景, 把它定位到左下角的, 两个场景都使用了反序列化 ( deserialize).
因为要定位医疗箱移动, 所以这里使用到了 flyTo 方法 .
- var renderCanvas = function (medical, duration) {
- ht.Default.startAnim({
- duration,
- easing(v, t) {
- return t
- },
- action(v, t) {
- outScreenG3d.flyTo(medical, { direction: [-5, 3, 5], distance: 300 })
- }
- })
- }
封装动画
如果要实现这么多的动画, 首先想到的是一个个物体进行移动的过程. 医疗箱的行走, 电梯的升降, 传送带运送医疗箱等我们都可以对他们的动作进行封装.
如图可以看到医疗箱总是在动, 所以定义了一个行走的动画, 每次医疗箱行走的距离, 行走方向, 动画的配置都进行传参.
这里要说明的参数:
- 1.node(对应的元素)
- 2.fn(动画执行完进行回调的函数)
- 3.config(动画配置)
- 4.coord(方向轴)
- // 行走动画
- walkAnim(node, fn, config, coord) {
- const { duration, space } = config
- const positionArray = node.p3()
- let isShadow = false
- let ShadowNode = null
- // 如果移动的元素是 icu 车或者供应车的话 获取它的阴影跟随元素移动
- if (node.getTag() === 'supply' || node.getTag() === 'icuCar') {
- isShadow = true
- ShadowNode = this.dm.getDataByTag(`${node.getTag()}Shadow`)
- }
- ht.Default.startAnim({
- duration,
- easing: function (t) {
- return t
- },
- action(v, t) {
- if (coord === 'x') {
- node.p3(positionArray[0] + t * space, positionArray[1], positionArray[2])
- isShadow && ShadowNode.p3(positionArray[0] + t * space, positionArray[1], positionArray[2])
- } else if (coord === 'y') {
- node.p3(positionArray[0], positionArray[1] + t * space, positionArray[2])
- isShadow && ShadowNode.p3(positionArray[0], positionArray[1] + t * space, positionArray[2])
- } else {
- node.p3(positionArray[0], positionArray[1], positionArray[2] + t * space)
- isShadow && ShadowNode.p3(positionArray[0], positionArray[1], positionArray[2] + t * space)
- }
- },
- finishFunc() {
- typeof fn === 'function' && fn(node)
- }
- })
- }
物体之间的影响
电梯的升降会影响很多东西, 比如频台的移动会带着传送带和医疗箱, 这里我用到了 sethost 吸附方法 (吸附: 节点指定宿主, 宿主进行改变会影响节点).
很多场景下非常合适, 我需要电梯升降的过程中带用医疗箱和频台一起上升, 还有医疗箱放到传送带的时候, 医疗箱要动起来, 感觉是这真的传送带在带动医疗箱进行运动.
这里要说明的参数:
- 1.node(操作的电梯元素)
- 2.medicalKit(医疗箱)
- 3.fn(动画执行完进行回调的函数)
- 4.status (电梯上升和下降的状态)
- 5.config(动画配置)
- // 电梯升降动画
- elevatorAnim(node, medicalKit, fn, status, config) {
- const self = this
- // 获取电梯的 index 让对应的频台也跟着动
- const elevatorIndex = node.getTag().replace(/[^0-9]/ig, '') - 0
- // 获取医疗箱的 index 控制电梯升降的距离
- const medicalKitIndex = medicalKit.getTag().replace(/[^0-9]/ig, '') - 0
- const positionArray = node.p3()
- const station = self.dm.getDataByTag(`station${elevatorIndex}`)
- // 吸附宿主
- station.setHost(node)
- medicalKit.setHost(node)
- // 设置升降状态
- if (elevatorIndex === 3) self.elevatorRunning = true
- // 升降距离 status 为 0 的时候是下降 最低部位的距离是固定的 所以只需要控制上升的距离
- const medicalKitLevel = self.returnMedicalKitLevel(medicalKitIndex)
- // 电梯的属性
- // 最低点的位置 Lowest
- // 如果有轨道的话 就去轨道的位置 否则就按照层数 orbitalP
- // 第一层的位置 distance
- let space
- const addSpace = medicalKitIndex === 7 ? 100 : 0
- if (status == 1) {
- space = config.orbitalP ? config.orbitalP : config.distance + addSpace + (400 * medicalKitLevel)
- } else {
- space = config.Lowest
- }
- // 下降状态时 医疗箱不会做动作
- if (status === 0) {
- medicalKit.setHost()
- }
- return ht.Default.startAnim({
- duration: config.orbitalP ? 2000 : (medicalKitLevel === 0 && elevatorIndex == 3 ? 700 : 2500 + (medicalKitLevel * 1000)),
- action(v, t) {
- node.p3(
- positionArray[0],
- positionArray[1] + ((space - positionArray[1]) * t),
- positionArray[2]
- )
- },
- finishFunc() {
- station.setHost()
- typeof fn === 'function' && fn(node)
- }
- })
- }
动画暂停
动画的过程中有个问题需要处理就是等待电梯的动画, 医疗箱在动画过程中, 需要判断电梯是否在上升, 如果不在地面的话, 需要等待.
我的思路是, 当医疗箱走到离电梯一点距离的时候, 需要判断电梯是否在上升状态, 如果是的话, 需要调用动画暂停的方法.
当 elevatorRunning 为 false 的时候代表电梯没有运动, 否则在运动中.
电梯动画开始的时候设置为 true, 结束后设置变量为 false, 就可以监控它的状态了.
ht.Default.startAnim 方法会返回一个实例, 通过实例的方法可以对当前动画进行一些操作.
- const anim = ht.Default.startAnim({
- duration,
- action(v, t) {
- node.p3(
- positionArray[0],
- positionArray[1],
- positionArray[2] - (tpMax - positionArray[2]) * t
- );
- if (index> 1 && self.elevatorRunning === true) {
- if (node.p3()[2] <= stopMax) {
- anim.pause();
- const t = setInterval(() => {
- if (self.elevatorRunning === false) {
- anim.resume();
- clearInterval(t);
- }
- }, 100);
- }
- }
- },
- finishFunc() {
- typeof fn === "function" && fn();
- }
- });
- return anim;
事件监听 (发布, 订阅)
因为需要监听某个当前动画的结束, 然后进行相机位移.
如图, 我需要监听第一个 3d 场景中显示提示文字动画结束, 然后执行第二个 3d 场景的显示. 因为 2 个是不同的场景, 是不能用回调的方法监听到的, 所以这里就用到了 eventBus 事件总线.
下面是 eventBus 的使用, 第一个参数代表要监听的注册函数名, 第二个是回调函数.
- // 事件总线 监听事件
- eventbus.on('animation1', _ => {
- const medical = dm.getDataByTag('medicalKit1')
- renderView(medical, dm, gv)
- })
下面是 eventBus 发射的使用, 第一个参数代表要触发的函数名, 第二个是发射给函数的参数.
- // 触发事件
- eventbus.emit("animation1", null);
总结
做完这个 demo 之后, 除了对 HT for web 更加熟练之外, 对物联网也有了更深刻的概念.
我身为一名前端工作者, 在这个时代感觉非常的自豪, 因为我能通过自己的技能创造出许多能造福和改善人们生活的东西.
希望大家看到我的 demo 能够得到一些启发, 同时也要相信自己能够创造不可能, 为社会做出贡献.
来源: https://www.cnblogs.com/htdaydayup/p/11558748.html