基于 HTML5 + WebGL 的无人机可视化系统

析构潮汐
• 阅读 1120

前言

近年来,无人机的发展越发迅速,既可民用于航拍,又可军用于侦察,涉及行业广泛,也被称为“会飞的照相机”。但作为军事使用,无人机的各项性能要求更加严格、重要。本系统则是通过 Hightopo 的  HT for Web  产品来搭建的一款 无人机 3D 可视化系统,通过对无人机及其信息的全景展示来模拟无人机状态的监控。

系统中包含 4 种展示模式:实体模式 、热力模式、线框模式和内部模式,通过飞机下方操作按钮即可进行模式切换。

预览地址:http://www.hightopo.com/demo/Drones/

实现过程

  • 加载界面采用 2D 拓扑组件进行绘制,全矢量化图标,与传统的 png、jpg 等格式的图片相比,完美适配移动端、PC 端、大屏等各种尺寸及分辨率屏幕,不会出现失真情况。
  • 无人机及周边信息面板采用 3D 引擎进行场景搭建,用户可从场景任意位置对无人机进行查看。
  • 动画过程采用产品提供的动画函数 ht.Default.startAnim 来驱动图形属性值的改变,应用其 Time-Based 的方式,只需要指定动画周期 duration 的毫秒数,由系统去计算帧数或 action 函数被调用的次数,以保证更加高效、平滑的进行动画过程。

界面

 基于 HTML5 + WebGL 的无人机可视化系统

加载界面中通过动态改变图形的属性值来展现加载进度,加载完毕后通过动画的 finishFunc 调用 hidden2d 方法来改变图形的透明度,在此之后通过 moveCamera 将场景内视角拉近,从而实现淡出到淡入的效果(即离开加载界面进入到 3D 场景中)。与此同时改变图形在 3D 场景中位置来实现各形态的无人机合为一体以及将对应按钮分离。

// 加载进度
function loadAnim(){
  ht.Default.startAnim({
    duration: 6000,
    easing: t => {
      return 1 - (--t) \* t \* t \* t;
    },
    action: (v, t) => { 
      loge.s('clip.percentage', v);
      percentText.s('text', Math.floor(v \* 100));
    },
    finishFunc: () => { hidden2d()
    }
  })
}

// 隐藏 2d 图纸
function hidden2d(){
  ht.Default.startAnim({
    duration: 500,
    easing: t => {
      return t;
    },
    action: (v, t) => { 
      dm2d.each(e => {
        e.s('opacity', 1 - v);
      })
    },
    finishFunc: () => {
      dm2d.setBackground('');
      g3d.moveCamera(eye, center, {duration: 3000, easing: t => {return 1 - (--t) \* t \* t \* t;}});
      planeFit();
      buttonSeparate();
    }
  })
}

 2D 界面的制作是绘制了一张图纸,而 logo 则是制作了一个图标,一个图标可以在图纸中进行多次使用,并可展示不同的样子。下图中右侧的四个 logo 就是同一个图标,分别展示了不同的裁切方式以及透明度,系统中 logo 的进度条效果就是动态的去改变图标的裁切比例来实现,而界面的淡出效果则是改变透明度。整个图标的制作是绘制不同的图形组合而成,这些图形我们也可以去改变颜色,形成左侧的 logo 样式。

基于 HTML5 + WebGL 的无人机可视化系统

无人机形态切换

基于 HTML5 + WebGL 的无人机可视化系统

无人机主体形态分为三种:实体模式、线框模式和热力模式。通过点击下方按钮,可切换至按钮所对应的形态。切换的过程中,将目标形态进行显示,并分别上下移动目标形态和原形态,使用户可以短暂的进行同时查看,之后再回归原位并将原形态进行隐藏。隐藏的方式则有所不用,线框模式是改变线框颜色,其余两种模式则是调整模型的透明度。这里的线框是根据模型的轮廓生成的,通过 3D 引擎自动计算描绘,非常便捷。

// 选择展示机型
function select(data){
  const name = data.getDisplayName();
  const moveData = dm3d.getDataByTag(name);
  const normalP = normalPlane.p3();

  ht.Default.startAnim({
    duration: 1000,
    easing: t => {
      return 1 - (--t) \* t \* t \* t;
    },
    action: (v, t) => {
      if(name === 'linePlane'){
        moveData.s('wf.color', 'rgba(64,173,152,' + v + ')');
      }
      else{
        moveData.s('shape3d.opacity', v);
      }
      moveData.p3(normalP\[0\], normalP\[1\] + (4500 - normalP\[1\]) \* v, normalP\[2\]);
      isShow.p3(normalP\[0\], normalP\[1\] + (2500 - normalP\[1\]) \* v, normalP\[2\]);

      hiddenRing(v);
    },
    finishFunc: () => {
      isShow.s('shape3d.transparent', true);

      ht.Default.startAnim({
        duration: 1000,
        easing: t => {
          return 1 - (--t) \* t \* t \* t;
        },
        action: (v, t) => { 
          if(isShow.getTag() === 'linePlane'){
            isShow.s('wf.color', 'rgba(64,173,152,' + (1 - v) + ')');
          }
          else{
            isShow.s('shape3d.opacity', 1 - v);
          }
          moveData.p3(normalP\[0\], 4500 + (normalP\[1\] - 4500) \* v, normalP\[2\]);
          isShow.p3(normalP\[0\], 2500 + (normalP\[1\] - 2500) \* v, normalP\[2\]);

          showRing(v);
        },
        finishFunc: () => {
          isShow = moveData;
          if(moveData.getTag() === 'normalPlane'){
            moveData.s('shape3d.transparent', false);
          }
          isAnim = false;
        }
      });
    }
  });
}

通过 3D 引擎,我们可以生成立体图形,也可以添加导入的模型,图形的位置由 x、y、z 三个方向的坐标来确认,而坐标轴汇聚的原点则是图形的锚点,无人机前方旋转的圆环则是将锚点调整到圆环中心后,操纵 rotation 属性进行转动 。在系统中线框状态的无人机则是像图中左侧的球体这样生成的,如果我们将图形的透明度调为 0,则只显示线框的样式。

基于 HTML5 + WebGL 的无人机可视化系统

内部结构

基于 HTML5 + WebGL 的无人机可视化系统

在线框模式下,大家会发现按钮的上方出现了一个小按钮,点击它就可以进入到无人机的另一个状态,在这里我们除了可以看到线框,还能够接触到无人机的内部结构,查看它的每一个部件。进入的过程会将场景内的其它图形隐藏,将内部结构显示出来。

// 内部模式
function moveToInternal(){
  const width = background.getWidth();   // 获取背景当前宽度
  const beginLeft = -(width / 2 - 960);   // 计算两侧节点起始位置
  const beginRight = width / 2 + 960;

  ht.Default.startAnim({
    duration: 2000,
    easing: t => {
      return t;
    },
    action: (v, t) => { 
      linePlane.s('wf.color', 'rgba(64,173,152,' + (1 - v) + ')');
      hiddenRing(v);
    },
    finishFunc: () => {
      dm3d.each(e => {
          e.s('3d.visible', false)
      })

      linePlane\_internal.each(e => {
        e.s('3d.visible', true);
      })

      ht.Default.startAnim({
        duration: 1000,
        easing: t => {
          return 1 - (--t) \* t \* t \* t;
        },
        action: (v, t) => { 
          title.setY(-50 + (70 + 50) \* v);
          returnButton.setY(1095 + (1020 - 1095) \* v);
          leftShape.setX(beginLeft + 130 \* v);
          rightShape.setX(beginRight - 130 \* v);
        }
      })
    }
  })
}

接下来,我们探索一下进入内部模式时,从四周缓缓移入窗口的图形又是怎么实现的

基于 HTML5 + WebGL 的无人机可视化系统

现如今,终端的屏幕分辨率各式各样,很多网页在开发前期都会选择响应式布局或自适应式布局,而 HT for Web的 2D 拓扑组件除了提供矢量绘制,还提供了一套相契合的布局方式。从上图中我们可以看到,红框中的部分是最开始的加载界面,而红框四周的部分则是内部模式中移入的部分,系统中的加载页面与此不同,正是因为添加了布局方式。

首先我们将红框中背景图片选为整个页面根节点,修改它的 fullscreen 属性为 fill,并为其添加全屏锁定的方式。其次将根节点设置为其余节点的吸附节点,并为其余节点修改合适的布局方式。这样背景图片就会填充整个界面,而四周节点的位置则始终保持在背景图片的外侧,在加载界面中就不会显示出来了。内部模式将四周节点移动至界面内,也是通过修改位置来实现的,但是因为全屏锁定方式设置为垂直,所以背景的宽度被改变,左右两侧节点的移动则需要在获取到当前界面显示宽度后去计算移动位置。

总结

现如今,信息化快速发展,智能化工具成为了新生产力出现在我们的生活中。与此同时,工业互联网的概念也随之诞生,将人、数据、设备联系到了一起,而可视化界面则可以很好的将数据和设备进行展示,方便管理的同时也更加安全、高效。

HT for Web 提供了 2D、3D 两种模式的可视化方式,它功能强大的同时也易于学习使用,有兴趣的同学也可以来体验一下。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
5G“乍到”,图扑带你了解室内定位可视化的实现与新突破
前言现代工业化的推进在极大加速现代化进程的同时也带来的相应的安全隐患,在传统的可视化监控领域,一般都是基于WebSCADA的前端技术来实现2D可视化监控,本系统采用Hightopo的HTforWeb产品来构造轻量化的3D可视化场景,该3D场景从正面展示了一个现代化工厂的现实场景,室内定
Wesley13 Wesley13
3年前
OSC职位推荐:DJI 大疆创新,只招聘偏执狂
大家好,今天给各位推荐的公司——大疆创新(DJI)是深圳土生土长的科技企业,被称为无人机领域的“苹果”,它被《华尔街日报》称为“首个在全球主要的消费产品领域成为先锋者的中国企业”。提大疆都想到无人机,但其实大疆是做飞控起家,汪峰向章子怡求婚用的便是大疆无人机精灵系列的最新款。小编之所以推荐这家公司,是因为当下智能设备行业大热,相信大疆创新的技术和市
无人机集群自组织搜索仿真模型设计与实现
摘要:城市威胁背景下无人机集群自组织搜索移动目标问题,是无人机集群作战应用的一个重要发展方向。采用基于Agent的复杂系统建模仿真工具,构建了无人机集群搜索仿真模型框架,设计实现了无人机集群自组织搜索模型。在考虑无人机集群作战可能受到威胁的背景下,展示了无人机集群自组织搜索概念,探索了使用基于概率的有限状态机模型实现集群自主决策的解决方案,并通过案例进行了分
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究