0%

vue2整合3d

npm导入

默认导入是最新版本,必须选定版本号才可登录

1
npm show three versions  

查看所有的版本

找到符合vue2的版本进行下载

1
npm install three@0.126.1 --save

vue代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
 
<div ref="container" style="width: 100%; height: 600px; position: relative; top: -300px;" class="threeD"></div>


// 导入 Three.js 主模块
import * as THREE from 'three'
// 从 three/examples/jsm 目录导入 GLTFLoader(three@0.126.1 已支持ES模块导入)
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

// 导入 OrbitControls 用于交互旋转和缩放
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

data() {
return {
scene: null,
camera: null,
renderer: null,
loader: null,
model: null,
controls: null,
animationId: null,
raycaster: new THREE.Raycaster(),
mouse: new THREE.Vector2(),
selectedObject: null,
}


mounted() {

this.initScene();
this.loadModel();
this.animate();
window.addEventListener('resize', this.onResize);
this.$refs.container.addEventListener('click', this.onClick, false);
},
beforeDestroy() {
// 清除窗口事件监听和动画循环
window.removeEventListener('resize', this.onResize);
cancelAnimationFrame(this.animationId);
if (this.renderer) {
this.renderer.dispose();
}
},
methods: {
// 初始化场景、相机、光照和渲染器,并配置 OrbitControls
initScene() {
const container = this.$refs.container;
const width = container.clientWidth;
const height = container.clientHeight;

// 创建场景
this.scene = new THREE.Scene();

// 创建透视相机
this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
// 设置俯视视角:相机高高在上,y = 20,z = 0
// this.camera.position.set(100, 60, 200);
this.camera.position.set(25,15,50);

// 让相机朝下看
this.camera.lookAt(new THREE.Vector3(0,0,0));
this.scene.add(this.camera);


// 添加环境光和方向光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
this.scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 7.5);
this.scene.add(directionalLight);

// 创建渲染器,开启抗锯齿与透明背景
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setSize(width, height);
container.appendChild(this.renderer.domElement);

// 初始化 OrbitControls 实例,关联相机和渲染器 DOM 元素
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
// 开启阻尼效果,提升控制的流畅性
this.controls.enableDamping = true;
this.controls.dampingFactor = 0.25;
// 允许缩放(可选)
this.controls.enableZoom = true;
},
// 使用 GLTFLoader 加载 GLB 模型
loadModel() {
this.loader = new GLTFLoader();
// 模型文件放在 public/models 目录下
this.loader.load(
'/models/model.glb',
(gltf) => {
this.model = gltf.scene;
// 根据需要调整模型的缩放、位置及旋转
this.model.scale.set(1, 1, 1);
this.model.position.set(0, 0, 0);
this.scene.add(this.model);
},
(xhr) => {
console.log(`模型加载进度:${(xhr.loaded / xhr.total) * 100}%`);
},
(error) => {
console.error('加载 GLB 模型出错:', error);
}
);
},
// 动画循环,更新控制器和渲染场景
animate() {
this.animationId = requestAnimationFrame(this.animate);
// 更新 OrbitControls,确保交互效果平滑
if (this.controls) {
this.controls.update();
}
this.renderer.render(this.scene, this.camera);
},
// 监听窗口大小变化,调整相机和渲染器
onResize() {
const container = this.$refs.container;
const width = container.clientWidth;
const height = container.clientHeight;
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(width, height);
},

// 点击事件处理
onClick(event) {
const rect = this.$refs.container.getBoundingClientRect();
// 计算鼠标点击位置归一化坐标(-1 到 1)
this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;

this.raycaster.setFromCamera(this.mouse, this.camera);

// 获取所有可拾取的模型子对象
const intersects = this.raycaster.intersectObjects(this.model.children, true);

if (intersects.length > 0) {
const selected = intersects[0].object;
this.selectedObject = selected;

console.log('点击了对象:', selected.name || selected.uuid);

// 可选:显示提示信息
// alert(`你点击了部件:${selected.name || '未命名对象'}`);
}
},
}
}

模型文件放在 public/models 目录下。 ‘/models/model.glb’, 替换名字即可

以下是效果图