当前位置:Web前端 > > 正文

webgl api 源码(基于 HTML5 WebGL 实现的医疗物流系统)

时间:2021-10-03 01:38:23类别:Web前端

webgl api 源码

基于 HTML5 WebGL 实现的医疗物流系统

前言

物联网( IoT ),简单的理解就是物体之间通过互联网进行链接。世界上的万事万物,都可以通过数据的改变进行智能化管理。IoT 的兴起在医疗行业中具有拯救生命的潜在作用。
不断的收集用户信息并且实时的进行诊断,所以未来  IoT 肯定在医疗行业的应用会呈覆盖性。下面是我最近做的一个医疗物流系统,用来观察医疗物流过程。

webgl api 源码(基于 HTML5 WebGL 实现的医疗物流系统)

ht官网链接:http://www.hightopo.com/cn-index.html

demo链接: https://www.hightopo.com/demo/pivas/
 

实现过程

增加光源

 整个原场景其实是非常暗的,所以需要使用灯光的效果照亮整个场景,使其接近真实世界的场景。

 我们看下对比。

webgl api 源码(基于 HTML5 WebGL 实现的医疗物流系统)

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 )。

    webgl api 源码(基于 HTML5 WebGL 实现的医疗物流系统)

     因为要定位医疗箱移动,所以这里使用到了 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)
                }
            })
        }
    
  • 动画方法

     动画的过程中有个问题需要处理就是等待电梯的动画,医疗箱在动画过程中,需要判断电梯是否在上升,如果不在地面的话,需要等待。

    webgl api 源码(基于 HTML5 WebGL 实现的医疗物流系统)

     我的思路是,当医疗箱走到离电梯一点距离的时候,需要判断电梯是否在上升状态,如果是的话,需要调用动画暂停的方法。

     当 elevatorRunning 为 false 的时候代表电梯没有运动,否则在运动中。

     电梯动画开始的时候设置为 true,结束后设置变量为 false,  就可以监控它的状态了。

     ht.Default.startAnim 方法返回一个实例,利用 action 方法, 实现轮询监听动画状态,然后进行操作。

     当 elevatorRunning 为 true 的话, 使用 anim.pause() 暂停当前动画。

     当 elevatorRunning 为 false 的话, 使用 anim.resume() 继续当前动画。

  • 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();
       }
    });
    
  • 事件监听(发布、订阅)

     因为需要监听某个当前动画的结束,然后进行相机位移。

     如图,我需要监听第一个 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 能够得到一些启发,同时也要相信自己能够创造不可能,为社会做出贡献。

    上一篇下一篇

    猜您喜欢

    热门推荐