Bootstrap

站在JavaScript的视角去看,HTML的DOM和GLTF的Json数据。

很多前端小伙伴没有见过、操作过gltf文件,对非常懵逼,本文从前端小伙伴最熟悉的dom模型为切入口,以类别的方式来学习一下gltf文件。

一、结构与组织形式

  • HTML DOM(文档对象模型)
    • 树形结构:HTML DOM 将 HTML 页面表示为一个树形结构,树的根节点是 document 对象,每个 HTML 元素(如 <div>、<p>、<img> 等)都是树上的节点,节点之间存在父子、兄弟等层级关系。例如,一个简单的 HTML 页面结构如下:
<!DOCTYPE html>
<html>

<body>
    <div id="main">
        <p>这是一段文本</p>
        <img src="image.jpg" alt="示例图片">
    </div>
</body>

</html>

在 DOM 中,document 是根,body 是 document 的子节点,div 又是 body 的子节点,p 和 img 则是 div 的子节点,以此类推形成一棵完整的树。

  • 标签属性与文本内容:每个 DOM 节点有对应的 HTML 标签属性(如 id、class、src 等),同时可能包含文本内容(像 p 标签里的文字),这些属性和内容都可以通过 JavaScript 进行访问和修改。
  • GLTF JSON
    • 对象层次结构:GLTF 的 JSON 部分同样呈现出一种层次化的对象结构,不过它围绕着 3D 模型与场景的描述来组织。如前面所述,包含 asset、scenes、nodes、meshes 等不同层级的对象来完整定义 3D 资源,例如:
{
    "asset": {
        "version": "2.0",
        "generator": "SomeTool"
    },
    "scenes": [
        {
            "name": "Scene1",
            "nodes": [0]
        }
    ],
    "nodes": [
        {
            "name": "ModelNode",
            "translation": [0, 0, 0],
            "rotation": [0, 0, 0, 1],
            "scale": [1, 1, 1]
        }
    ],
    "meshes": [
        {
            "name": "Mesh1",
            "primitives": [
                {
                    "attributes": {
                        "POSITION": 0,
                        "NORMAL": 1
                    },
                    "indices": 2,
                    "material": 0
                }
            ]
        }
    ]
}

这里不同的对象相互关联,共同构建起 3D 模型在场景中的布局、几何形状、外观等信息的描述体系。

  • 特定语义字段:有着众多用于描述 3D 相关概念的特定字段,像节点的位置(translation)、旋转(rotation)、缩放(scale)属性,材质相关的 pbrMetallicRoughness 等字段用于定义外观,与 HTML DOM 基于 HTML 标签属性的组织方式有明显不同的语义内涵。

二、JavaScript 操作目的

  • HTML DOM
    • 页面交互与动态更新:主要用于实现网页的交互效果,例如响应用户的点击事件(通过给 DOM 元素添加 onclick 等事件监听器),动态修改页面内容(改变元素的文本、样式属性等),实现页面的局部刷新、元素的显示隐藏、动画效果等。比如以下 JavaScript 代码可以改变一个 p 标签的文本内容:
const pElement = document.querySelector('p');
pElement.textContent = '新的文本内容';

  • DOM 遍历与查询:常常需要在 DOM 树中查找特定的元素,可通过像 document.getElementById、document.querySelectorAll 等方法来定位元素,以便后续进行相关操作。例如,获取所有具有某个类名的元素:
const elements = document.querySelectorAll('.my-class');
  • GLTF JSON(通过 JavaScript 在相关 3D 应用场景下操作)
    • 3D 模型渲染与展示:JavaScript 代码配合 WebGL 等 3D 渲染技术,读取 GLTF JSON 中的结构和属性信息,将 3D 模型渲染到浏览器页面或其他支持的平台上。比如解析 nodes 的位置和 meshes 的几何形状等数据,构建相应的 3D 图形对象用于渲染。
    • 3D 场景交互与修改:实现对 3D 场景中模型的交互操作,像根据用户输入旋转、平移模型(通过修改 nodes 的 translation、rotation 等属性),或者动态更换模型的材质(改变 materials 相关的配置字段)等。以下是简单示意如何修改一个 GLTF 模型节点的位置(假设已经有解析 GLTF 并获取到对应节点对象的代码基础):
const modelNode = getModelNodeFromGltf(); // 假设的获取节点方法
modelNode.translation[0] = 1; // 改变 x 轴坐标位置
modelNode.translation[1] = 0.5; // 改变 y 轴坐标位置
// 然后重新渲染场景以体现位置变化
renderScene();


 

三、操作方式与 API

  • HTML DOM
    • 标准 DOM API:JavaScript 内置了一套完善的 DOM API,涵盖了元素的创建(如 document.createElement)、添加删除(parentElement.appendChild、parentElement.removeChild)、属性获取与设置(element.getAttribute、element.setAttribute)等丰富的操作方法,开发者可以直接使用这些接口来操作 DOM 树。
    • 事件处理机制:有专门的事件绑定和监听机制,通过给元素添加类似 onclick、onmouseover 等事件属性(或者使用 addEventListener 方法)来响应各种用户操作引发的事件,从而实现交互逻辑。例如:
const button = document.createElement('button');
button.textContent = '点击我';
button.addEventListener('click', function () {
    alert('你点击了按钮');
});
document.body.appendChild(button);

  • GLTF JSON
    • 自定义解析与处理逻辑:并没有像 DOM API 那样统一内置在 JavaScript 语言环境中的标准 API 来操作 GLTF JSON。通常需要借助第三方的 GLTF 解析库(如 three.js 中相关的 GLTF 加载和处理模块等),这些库会提供自己的一套方法来解析 JSON 数据,将其转换为便于操作的 JavaScript 对象,再基于这些对象进行如前面提到的 3D 相关操作。例如使用 three.js 加载 GLTF 文件并操作模型的简单代码示例:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

const scene = new THREE.Scene();
const loader = new GLTFLoader();

loader.load('model.gltf', function (gltf) {
    const model = gltf.scene;
    scene.add(model);
    // 后续可以对 model 进行如位置等属性的修改等操作
    animate(); // 假设的渲染循环函数用于展示模型
}, function (xhr) {
    console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}, function (error) {
    console.log('An error happened', error);
});
  • 与 3D 渲染集成:操作 GLTF JSON 往往是和 3D 渲染紧密结合的,在解析出模型结构等信息后,需要将其传递给合适的 3D 渲染引擎(如 WebGL 底层结合 three.js 这样的上层库)来进行实际的图形绘制,而不像 DOM 操作主要聚焦于页面结构和内容展示层面的 2D 处理。

四、数据变化频率与更新特点

  • HTML DOM
    • 高频率动态变化:在现代网页应用中,DOM 的更新频率往往较高,尤其是在实现复杂交互界面、实时数据展示(如聊天窗口、实时图表等场景)时,会频繁地修改 DOM 元素的属性、内容或者添加删除元素,以响应用户操作和后端推送的数据变化。
    • 局部更新与重绘:为了性能优化,通常会采用局部 DOM 更新的方式,只改变需要变化的部分,浏览器会智能地进行对应的局部重绘,避免整个页面重新渲染,像使用 innerHTML 等属性有选择地更新某个元素内部内容或者通过 classList 修改元素的类名来切换样式实现动态效果。


  •  
  • GLTF JSON(在 3D 场景中)
    • 相对低频变化(取决于应用场景):在一些静态 3D 展示场景中,模型和场景的结构等数据一旦加载解析完成后可能长时间不会变动;而在交互性较强的 3D 应用(如 3D 游戏中角色模型动作变化等),其数据变化频率会随着用户交互而变高,但总体相对 DOM 在常规网页交互中的更新频率还是可能稍低一些。
    • 整模型或场景更新关联渲染:当对 GLTF JSON 里的关键数据(如模型的几何形状、材质、节点位置等)进行修改后,一般需要重新进行整个模型或者相关部分的 3D 渲染,不像 DOM 那样可以较细粒度地进行局部内容更新,因为 3D 图形的渲染是基于完整的模型数据和场景配置来进行的。

总体而言,HTML 的 DOM 文件和 GLTF 的 JSON 文件从 JavaScript 操作角度有着不同的结构特点、操作目的、方式以及数据更新特点,分别服务于网页 2D 交互展示和 3D 模型相关应用这两个不同的应用场景需求。

;