前言
关于实现这个功能,Three 中提供了 GLTFExporter
,OBJExporter
导出器。
但是这两个类的使用方法,跟你的Three版本有很大的关系。不同的版本,实现方式是不一样的,代码上会有区别。所以,继续往下看时,请务必先确认你当前的Three版本。
【更新】2025-03-18:请把你的three.js版本打在评论里。
GLTF
import * as THREE from 'three';
// 下面这个导入的路径看你的文件路径关系,不要搞错了(我这里是使用第一种)
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
// import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
// 创建你的模型
let myModel = new THREE.Mesh(
new THREE.SphereGeometry(20, 10, 10),
new THREE.MeshStandardMaterial({
color: 0xffff00,
metalness: 0.5,
roughness: 1.0,
flatShading: true
})
);
myModel.position.set( 0, 0, 0 );
myModel.name = 'my-Sphere';
scene.add(myModel)
// 导出器
const exporter = new GLTFExporter();
// 配置选项(可选)
const options = {
binary: false, // 导出为 .gltf
trs: false, // 不使用位移/旋转/缩放节点
onlyVisible: true, // 仅导出可见对象
includeCustomExtensions: true
};
// 执行导出
exporter.parse(myModel, (result) => {
const output = JSON.stringify( result, null, 2 );
// 保存文件
const blob = new Blob([output], { type: 'text/plain' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'mymodel.gltf';
link.click();
}, (error) => {
console.log( 'An error happened during parsing', error );
}, options);
【需要注意的是】这里的 exporter.parse() 方法,接受4个参数。不要错了!
glb
import * as THREE from 'three';
// 下面这个导入的路径看你的文件路径关系,不要搞错了(我这里是使用第一种)
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
// import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
// 创建你的模型
let myModel = new THREE.Mesh(
new THREE.SphereGeometry(20, 10, 10),
new THREE.MeshStandardMaterial({
color: 0xffff00,
metalness: 0.5,
roughness: 1.0,
flatShading: true
})
);
myModel.position.set( 0, 0, 0 );
myModel.name = 'my-Sphere';
scene.add(myModel)
const exporter = new GLTFExporter();
// 配置选项(可选)
const options = {
binary: true, // 导出为 .glb
trs: false, // 不使用位移/旋转/缩放节点
onlyVisible: true, // 仅导出可见对象
includeCustomExtensions: true
};
// 执行导出
exporter.parse(myModel, (result) => {
// 这里用 type: 'model/gltf-binary' , 或者 type: 'application/octet-stream' 都是可以的,问题不大。(关于这两者更详细的解释说明,我放到了文章最后)
const blob = new Blob([result], { type: 'model/gltf-binary' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'mymodel.glb';
link.click();
}, (error) => {
console.log( 'An error happened during parsing', error );
}, options);
可以使用一套公用代码来生成 glb / gltf:
import * as THREE from 'three';
// 下面这个导入的路径看你的文件路径关系,不要搞错了(我这里是使用第一种)
import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
// import { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
// 创建你的模型
let myModel = new THREE.Mesh(
new THREE.SphereGeometry(20, 10, 10),
new THREE.MeshStandardMaterial({
color: 0xffff00,
metalness: 0.5,
roughness: 1.0,
flatShading: true
})
);
myModel.position.set( 0, 0, 0 );
myModel.name = 'my-Sphere';
scene.add(myModel)
let param = {
binary: true
}
const exporter = new GLTFExporter();
// 配置选项(可选)
const options = {
binary: param.binary, // 导出为 .glb 或 .gltf
trs: false, // 不使用位移/旋转/缩放节点
onlyVisible: true, // 仅导出可见对象
includeCustomExtensions: true
};
// 执行导出
exporter.parse(myModel, (result) => {
if ( result instanceof ArrayBuffer ) {
const blob = new Blob( [ result ], { type: 'model/gltf-binary' } );
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'mymodel.glb';
link.click();
} else {
const output = JSON.stringify( result, null, 2 );
const blob = new Blob( [ output ], { type: 'text/plain' } );
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'mymodel.gltf';
link.click();
}
}, (error) => {
console.log( 'An error happened during parsing', error );
}, options);
【需要注意的是】这里的 exporter.parse() 方法,接受4个参数。不要错了!
obj
import * as THREE from 'three';
// 下面这个导入的路径看你的文件路径关系,不要搞错了(我这里是使用第一种)
import { OBJExporter } from 'three/examples/jsm/exporters/OBJExporter.js';
import { OBJExporter } from 'three/addons/exporters/OBJExporter.js';
// 创建你的模型
let myModel = new THREE.Mesh(
new THREE.SphereGeometry(20, 10, 10),
new THREE.MeshStandardMaterial({
color: 0xffff00,
metalness: 0.5,
roughness: 1.0,
flatShading: true
})
);
myModel.position.set( 0, 0, 0 );
myModel.name = 'my-Sphere';
scene.add(myModel)
const exporter = new OBJExporter();
const result = exporter.parse(myModel); // 直接返回字符串
// 保存文件
const blob = new Blob([result], { type: 'text/plain' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'mymodel.obj';
link.click();
STL
import * as THREE from 'three';
// 下面这个导入的路径看你的文件路径关系,不要搞错了(我这里是使用第一种)
import { STLExporter } from 'three/examples/jsm/exporters/STLExporter.js';
import { STLExporter } from 'three/addons/exporters/STLExporter.js';
// 创建你的模型
let myModel = new THREE.Mesh(
new THREE.SphereGeometry(20, 10, 10),
new THREE.MeshStandardMaterial({
color: 0xffff00,
metalness: 0.5,
roughness: 1.0,
flatShading: true
})
);
const exporter = new STLExporter();
const result = exporter.parse(myModel , { binary: true }); // 导出二进制格式
const blob = new Blob([result], { type: 'application/octet-stream' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'mymodel.stl';
link.click();
写在最后
1、关于下载 glb
文件时,type 用 model/gltf-binary
还是 application/octet-stream
的说明:
application/octet-stream
表示通用的二进制流数据,适用于所有未知或未注册的二进制文件。适用场景:无特定格式要求时使用,浏览器不会尝试解析文件内容,直接触发下载。model/gltf-binary
:根据 Khronos Group 对 GLB 格式的规范,.glb
的官方 MIME 类型为model/gltf-binary
,明确标识文件为二进制格式的 glTF 数据。部分工具或框架(如 Babylon.js、A-Frame)会根据此类型自动识别文件格式,提升兼容性。
2、Three.js 官网示例选择 application/octet-stream
的原因:
-
跨版本兼容性
Three.js 早期版本未强制要求严格符合 GLB 规范,使用通用类型可避免因 MIME 类型限制导致的下载失败。 -
简化代码逻辑
官网示例以功能实现为目标,application/octet-stream
能直接兼容所有场景,无需考虑外部工具对 MIME 类型的依赖。
3、建议选择 model/gltf-binary
的场景:
- 与其他工具集成时
若导出的.glb
文件需要导入到 Unity、Blender 或 Web 3D 框架中,使用规范类型可避免解析错误。 - 遵循最新规范时
2023 年后,主流 3D 工具已普遍支持model/gltf-binary
类型,符合行业标准。
—————————— 【正文完】——————————
前端学习交流群,想进来面基的,可以加Q群: 832485817,685486827;
写在最后: 约定优于配置 —— 软件开发的简约原则
——————————【完】——————————
我的:
个人网站: https://neveryu.github.io/neveryu/
Github: https://github.com/Neveryu
微信: 421354532
更多学习资源请关注我的微信…好吗