说明: 公司需要做此项目,之前都没接触过,所以个人集合了所有能找到的资料做出了一个demo项目出来,希望对需要的各位有帮助。
1.先导入3D模型: obj+mtl文件
注意:
(1)在导入模型之前需要手动去修改mtl文件里面的路径,因为若是不改的话会导致材质加载失败的问题
(2)所有的变量最好不要在data里面定义,因为模型大一点的话会卡顿等。目前我是在外部定义的。
模型需要放在根目录下,不然会读取不到。
2.使用three.js是由场景(网格模型(具体实物+材质)+光照(点光源(阴影)+环境光源))+相机+渲染(鼠标缩放拖动之类的)组成的。
我们先初始化
init() {
let container = document.getElementById("container");
/*
场景
*/
scene = new THREE.Scene();
/*
相机
*/
// scene.background = new THREE.Color( 0xa0a0a0 );
camera = new THREE.PerspectiveCamera(
75,
container.clientWidth / container.clientHeight,
1,
1000
);
camera.position.set(292, 109, 268);
camera.position.set(0, 0, 50);
}
复制代码
如果要拿图片做背景的话(直接添进初始化里面)
import BG from '../../public/xxxx.png'new THREE.TextureLoader().load(BG);
接着就是添加光源效果,如果不加的话会导致漆黑一片的效果。
// 环境光 能保持整体都是亮点
let ambientLight = new THREE.AmbientLight(0x999999);
// 点光源 就像灯泡一样的效果 白色灯光 亮度0.6
let pointLight = new THREE.PointLight(0xffffff, 0.8);
// 将灯光加入到场景中
scene.add(ambientLight);
// 将灯光加到摄像机中 点光源跟随摄像机移动
// 为什么这样做 因为这样可以让后期处理时的辉光效果更漂亮
camera.add(pointLight);
// 我们将摄像机加入到场景中
scene.add(camera);
复制代码
接着就是在初始化控制器(鼠标左右键的操作)
new OrbitControls(camera, renderer.domElement);
如果需要模型自动旋转的话autoRotate设为true就行了,他默认的是2.0, 你要是觉得快了可以调动autoRotateSpeed属性。
最大缩放效果与最小缩放效果是maxDistance/minDistance,他们的值是number。
3.加载模型
// 加载模型
loadObj() {
let _this = this;
let manager = new THREE.LoadingManager();
manager.addHandler(/\.dds$/i, new DDSLoader());
mtlloader.load("/model/6/1.mtl", (materials) => {
objloader.setMaterials(materials);
materials.preload();
objloader.load(
"/model/6/1.obj",
function (obj) {
// oldChildren = _this.dealMeshMaterial(obj.children);
obj.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material.transparent = true;
child.material.reflectivity = 0.9;
}
});
obj.scale.set(0.02, 0.02, 0.02);
obj.position.set(0, -7, 0);
scene.add(obj);
},fn(), fn2());
});
},
fn() // fn函数是成功调用
fn2 // fn2失败时调用
复制代码
如果需要加载进度的话就在fn函数获取进度值
4.点击高亮
当我们需要高亮时需要在初始化里面注册一个事件(本人觉得单机体验不好,就用了双击)
renderer.domElement.addEventListener("dblclick", this.mouseClick, false);
在加载模块时我是留住了每个模块的材质的
/**
* 留住每个模型的原材质
*/
dealMeshMaterial(arrs) {
let result = [];
for (let i = 0; i < arrs.length; i++) {
let obj = {
// name: arrs[i].name,
material: arrs[i].material,
uuid: arrs[i].uuid,
};
result.push(obj);
}
return result;
}
复制代码
点击事件
mouseClick(event) {
// 还原之前的 点击状态
this.showDetailBox = false;
this.restore(scene.children[2].children, oldChildren);
// 获取 raycaster 和所有模型相交的数组,其中的元素按照距离排序,越近的越靠前
let intersects = this.getIntersects(event, event.clientX, event.clientY);
// console.log(intersects);
// 获取选中最近的 Mesh 对象
if (
intersects.length != 0 &&
intersects[0].object instanceof THREE.Mesh
) {
selectObject = intersects[0].object;
if (this.isClick) {
this.showObject(selectObject, event);
} else {
console.log(1111);
}
} else {
// console.log(selectObject);
this.colseData();
}
}
复制代码
项目地址
注:此demo是用vue3.0来实现的,如果需要用vue2.0的话只需要把代码复制过去就行了。 定义的变量用的多的话 例:scene camera 这些变量需要在export default 外部定义,否则游览器会崩掉或者卡死。
gitee : https://gitee.com/chen_post/vue_three#compiles-and-hot-reloads-for-development