欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于 HTML5 Canvas 的 3D 渲染引擎界面以及吸附等效果的运用

程序员文章站 2022-03-12 19:57:44
HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打磨,如今 HT 算是达到了这样的效果,谈不上用尽洪荒之力,但我们对产品结果很满意,特别是 HT 的用... ......

前言

ht 是啥:everything you need to create cutting-edge 2d and 3d visualization.

这口号是当年心目中的产品方向,接着就朝这个方向慢慢打磨,如今 ht 算是达到了这样的效果,谈不上用尽洪荒之力,但我们对产品结果很满意,特别是 ht 的用户手册,将例子和文档无缝融合一体,小小 10 来兆开发包居然包含了四十五份手册,数百个活生生的 html5 例子,还没体验过的同学可以点击  ht 手册入口玩一玩。

这样综合并可搜索的手册入口居然还常被问及 ht 的 demo 在哪里?只能怪这些年深入人心的极致用户体验理念,把人惯得包括很多程序员都如此之“懒”,当然也怪我们没把用户体验的最后一公里做到位,将数百个手册例子进行了归类整理,最终形成了方便大家直观查找所有 ht 例子的页面: 。很明显,对于 ht 老用户包括我们自己做技术支持,都感觉查找例子更直观方便,但对于 ht 初学者,面对这一堆数百个涵括通用组件、网络拓扑图组件、3d 组件、矢量图形、各种编辑器等等五法八门的 html5 例子盛宴,往往无从下手。为此,老郑我打算为像我一样喜欢这方面的新手朋友多写几篇这样的博客,慢慢的给大家讲述各种各样的越来越多的有趣的小功能!

效果图

基于 HTML5 Canvas 的 3D 渲染引擎界面以及吸附等效果的运用

代码实现

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 渲染引擎组件,可视化呈现数据模型的三维环境场景。

datamodel = new ht.datamodel();
g3d = new ht.graph3d.graph3dview(datamodel);
g3d.addtodom();
window.addeventlistener('resize', function (e) {
  g3d.invalidate();
}, false);

我们还要设置眼睛(或camera)所在位置,默认值为 [0, 300, 1000] ,格式为 [x, y, z] 。

g3d.seteye([0, 300, 600]);

基于 HTML5 Canvas 的 3D 渲染引擎界面以及吸附等效果的运用

这里给大家说一下,可参考 3d 手册(  )。

基于 HTML5 Canvas 的 3D 渲染引擎界面以及吸附等效果的运用

然后我们再给它加上一些选中效果。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;
  }
});

接下来我们写个函数来方便绘制每个部分的模型:

function createnode (p3, s3, host) {
  // 拓扑图元类型
  var node = new ht.node();
  // 获取或设置图元中心点的三维坐标 有三个参数时相当于 setposition3d 没有相当于 get
  node.p3(p3);
  // 获取或设置图元的尺寸 有三个参数时相当于 setsize3d 没有相当于 get
  node.s3(s3);
  // 设置宿主图元,当图元吸附上宿主图元(host)时,宿主移动或旋转时会带动所有吸附者
  node.sethost(host);
  datamodel.add(node);
  return node;
}

讲到了这,我们来说说吸附,吸附功能对于设计有层次关系的模型非常方便,例如设备面板吸附上设备机框,设备端口吸附上设备面板,这样从机框 - 面板 - 端口的层次关系吸附,使得用户拖动整体机框时所有这个层次下的图元都会跟随移动。对于 3d 的场景下,吸附的概念更进一步延伸,当机框在三维空间进行任意位置偏移以及任意角度旋转时,所有吸附的相关图元都会正确的跟随平移,并做出相应位置对应的旋转,以达到整体设备各个图形部分保持物理相对位置一致。

基于 HTML5 Canvas 的 3D 渲染引擎界面以及吸附等效果的运用

下面我们来一起创建模型吧!分别是地板 floor,桌面 table,四个桌腿以及盒子:

// 地板
floor = createnode([0, 0, 0], [600, 5, 400]).s({
  'all.color': '#a0a0a0',// 六面颜色
  'label': '地板',// 图元文字内容
  'label.face': 'top',// 文字在3d下的朝向,可取值(left|right|top|bottom|front|back|center)
  'label.background': 'yellow',// 图元文字背景
  'label.position': 22,// 图元文字位置
  'label.t3': [10, 0, -10],// 文字在3d下的偏移,格式为 [x,y,z]
  'label.font': '28px arial, sans-serif'// 图元文字字体
});
// 桌面
table = createnode([0, 120, 0], [400, 10, 280], floor).s({
  'shape3d': 'cylinder',// 为空时显示为六面立方体,cylinder 圆柱
  'shape3d.side': 60,// 决定 3d 图形显示为几边型,为 0 时显示为平滑的曲面效果
  'shape3d.color': '#e5bb77',// 3d 图形整体颜色
  'label': '桌子',
  'label.face': 'top',
  'label.background': 'yellow',
  'label.position': 23,
  'label.t3': [0, 0, -10],
  'label.font': '20px arial, sans-serif'
});
// 四个桌腿
foot1 = createnode([100, 60, 80], [20, 110, 20], table).s({
  'shape3d': 'cylinder',
  'shape3d.color': '#e5bb77',
});
foot2 = createnode([-100, 60, 80], [20, 110, 20], table).s({
  'shape3d': 'cylinder',
  'shape3d.color': '#e5bb77',
});
foot3 = createnode([100, 60, -80], [20, 110, 20], table).s({
  'shape3d': 'cylinder',
  'shape3d.color': '#e5bb77',
});
foot4 = createnode([-100, 60, -80], [20, 110, 20], table).s({
  'shape3d': 'cylinder',
  'shape3d.color': '#e5bb77',
});
// 盒子
box = createnode([0, 150, 0], [100, 50, 60], table).s({
  'all.color': '#2e2f32',
  'front.color': '#bdc3c7',// 前面颜色
  'note': '盯着你看', // 图元冒泡标注
  'note.face': 'top',
  'note.position': 7,
  'note.t3': [0, 0, 10],
  'note.autorotate': true// 图标在 3d 下是否自动朝向眼睛的方向
});

代码中有一些属性,我已经帮大家写好了详细的注释。在此献上各种关于 'shape3d' 的图形的值,方便大家玩耍:

基于 HTML5 Canvas 的 3D 渲染引擎界面以及吸附等效果的运用

总结

这个小 demo 就说到这里吧,还有更多精彩想自己探索的朋友,可以直接去公司中文网站了解()。

我每周尽量都写一些技术随笔,既帮助自己整理知识,也能够跟大家一起学习,我们由浅至深,循序渐进。希望看了我的文章能得你们带来帮助,同时也希望大家能多多支持和鼓励!

上一篇: jq切换面板

下一篇: MySQL体系结构