主要介绍了预览 3D 文件的插件,如 vue-model-viewer、vue-3d-model、@google/model-viewer;也介绍了 three.js 的基础使用及配置,例如场景、相机、渲染器、轨道控制器、灯光等等
第三方插件
找到了如下第三方插件,用起来挺方便的,支持多种 3D 文件格式,包括 glb、gltf 等
但是不支持vue2.x,只支持vue3.x版
- vue-model-viewer:提供了一个 Vue 组件,使在 Vue 项目中集成和使用更加方便;支持多种 3D 文件格式,包括 glb、gltf 等
- vue-3d-model:简单易用,适合快速集成 3D 模型预览功能;支持多种 3D 文件格式
- @google/model-viewer:提供了丰富的交互和功能,如 AR 支持、动画、交互等。
正方体预览(three.js)
有一个红色的正方体 Box.glb 文件,
在GLTF 在线编辑器中预览效果如下所示:
项目之前用的是vue2.x版本,没法用上面的第三方工具,用three.js渲染展示
使用 three.js 预览,代码如下所示:
html
<template>
<div ref="container" style="width: 400px; height: 300px;"></div>
</template>
<script lang="ts">
// 导入three.js
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入gltf加载器
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 使用的是vue2.6.11版本
@Component
export default class bookUpload extends Vue {
mounted() {
this.initScene();
}
initScene() {
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, 400 / 300, 0.1, 1000);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(400, 300);
// 获取渲染元素
const container = this.$refs.container as HTMLElement;
container.appendChild(renderer.domElement);
// 添加光源
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 方向光颜色和强度
directionalLight.position.set(1, 1, 1); // 光源位置
scene.add(directionalLight);
// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
controls.dampingFactor = 0.05; // 阻尼系数
controls.rotateSpeed = 0.1; // 旋转速度
// 加载3D模型
const loader = new GLTFLoader();
loader.load("/Box.glb", (gltf) => {
console.log("gltf.scene", gltf.scene);
scene.add(gltf.scene);
});
// 设置相机在 z 轴上的位置
camera.position.z = 5;
const animate = () => {
requestAnimationFrame(animate);
controls.update(); // 更新控制器状态
renderer.render(scene, camera);
};
animate();
}
}
</script>
预览效果如下图所示:
3. 3D 图形预览(three.js)
js
// 初始化
this.$nextTick(() => {
this.list.forEach((item) => {
this.initScene(item);
});
});
// 渲染3D
initScene(item) {
// 1. 创建场景
const scene = new THREE.Scene();
// 设置背景色
scene.background = new THREE.Color(0xffffff);
// 设置背景图片(CubeTexture立方纹理 创建一个由6张图片所组成的纹理对象 左右上下前后)
// 设置背景图片(没生效,估计地址配置的不对 /public/img)
// scene.background = new THREE.CubeTextureLoader()
// .setPath("/img/")
// .load(["1.png", "2.png", "3.png", "4.png", "5.png", "6.png"]);
// 添加雾(配置的7,视角远一点 可以看到效果)
const fog = new THREE.Fog(0xcccccc, 0, 7);
scene.fog = fog;
// 2. 创建相机
// PerspectiveCamera透视相机,模拟人眼看到的景象,是3D场景中使用最普遍的投影模式
const camera = new THREE.PerspectiveCamera(75, 300 / 300, 0.1, 1000);
camera.position.z = 3; // 设置相机在 z 轴上的位置
camera.position.y = 1;
// (1)创建立方体
const box = new THREE.BoxGeometry();
// 创建材质(MeshBasicMaterial基础网格材质 不受光照影响)
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 创建网格
const cube = new THREE.Mesh(box, material);
cube.position.set(1, 1, 0);
scene.add(cube);
// 3. 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(300, 300); // 设置大小
renderer.setClearColor(0xffffff, 0); // 设置背景颜色 默认黑色
renderer.shadowMap.enabled = true; // 添加阴影的渲染
// 获取渲染元素
const container = document.getElementById(item.id) as HTMLElement;
container.appendChild(renderer.domElement);
// 添加网格地面
const gridHelper = new THREE.GridHelper(10, 10);
scene.add(gridHelper);
// 添加坐标轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 添加环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 添加平行光(需要设置位置)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); // 光颜色和强度
directionalLight.position.set(1, 1, 1); // 光源位置
scene.add(directionalLight);
// 添加灯光辅助
scene.add(new THREE.PointLightHelper(pointLight, 100));
// 添加点光源(看投影效果)
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.power = 500; // 设置亮度
pointLight.castShadow = true;
pointLight.position.set(2, 2, 2);
scene.add(pointLight);
// 4. 创建轨道控制器(调整相机位置,即视角位置)
const controls = new OrbitControls(camera, renderer.domElement);
// 监听控制器改变事件
// controls.addEventListener("change", () => {
// console.log("change");
// });
controls.enableDamping = true; // 允许阻尼效果,使动画更平滑
controls.dampingFactor = 0.05; // 阻尼系数
controls.rotateSpeed = 0.1; // 旋转速度
controls.autoRotate = true; // 自动旋转
controls.autoRotateSpeed = 0.5; // 自动旋转速度
// (2)加载3D模型
// 创建GLTF实例
const loader = new GLTFLoader();
// 加载模型
loader.load(
item.nftFileUrl,
(glb) => {
console.log("glb.scene", glb.scene);
// 遍历模型中的物体
glb.scene.traverse((child) => {
child.castShadow = true; // 设置物体投影
child.receiveShadow = true; // 设置物体接收阴影
})
// 添加到场景
scene.add(glb.scene);
}
);
// 5. 动起来
const animate = () => {
requestAnimationFrame(animate);
controls.update(); // 更新控制器状态
cube.rotation.x += 0.01; // 让立方体旋转起来
renderer.render(scene, camera); // 重新渲染
};
animate();
}
注意:通过 GLTFLoader 加载模型后,是一片黑色的,首先考虑灯光问题,需要添加灯光
。AmbientLight 为环境光;DirectionalLight 为平行光;PointLight为点光源