持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
写在前面
本文用vue+threejs控制相机聚焦到某物体。
以下是演示gif:
代码说明
- html和css
创建一个id,用于存放threejs渲染器节点。创建三个按钮:【小狗】、【女孩】、【树】,点击对应的按钮聚焦到对应的物体。
<template>
<div class="item">
<div id="THREE49"></div>
<div class="btn_box">
<el-button @click="focusDog">小狗</el-button>
<el-button @click="focusGirl">女孩</el-button>
<el-button @click="focusTree">树</el-button>
</div>
</div>
</template>
<style lang="less" scoped>
.btn_box {
position: absolute;
top: 10px;
left: 210px;
}
</style>
- 按钮事件
点击按钮之后,通过调整控制器的焦点和相机位置来实现聚焦到某物体。至于如何获取控制器的焦点和相机位置在下面的render()方法中会说到。
focusDog() {
this.controls.target.set(-5, 1.8, -10.5); // 控制器的焦点
this.camera.position.set(-4.8, 2.7, 13.6); // 相机位置
this.controls.update();
},
focusGirl() {
this.controls.target.set(2.7, 9.7, -10); // 控制器的焦点
this.camera.position.set(-10.5, 8, 43); // 相机位置
this.controls.update();
},
focusTree() {
this.controls.target.set(42.4, 29.1, -4.8); // 控制器的焦点
this.controls.update();
},
- 引入threejs和需要的模块
OrbitControls - 轨道控制器,需要改变它的焦点
GLTFLoader - 引入模型需要的加载器
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
- data()中定义的变量
camera相机,scene场景,gltfLoader模型加载器,renderer场景渲染器,controls轨道控制器,manager模型加载进度管理
data() {
return {
camera: null,
scene: null,
gltfLoader: null,
renderer: null,
controls: null,
manager: null,
};
},
- mounted()方法中调用的函数
每个函数的意义在代码种都有说明
mounted() {
this.manager = new THREE.LoadingManager();
this.gltfLoader = new GLTFLoader(this.manager);
this.initScene(); // 创建场景
this.initCamera(); // 创建相机
this.initLight(); // 创建灯光
this.initRenderer(); // 创建渲染器
this.initControls(); //创建轨道控制器
this.initModel(); // 加载模型
this.manager.onLoad = () => {
this.render();
console.log("Loading complete!");
};
},
- 创建场景
创建场景并设置背景颜色
initScene() {
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x000000); // 设置场景背景颜色
},
- 创建相机
创建一个透视相机并设置相机的位置
initCamera() {
this.camera = new THREE.PerspectiveCamera(
35,
(window.innerWidth - 201) / window.innerHeight,
1,
600
); // 透视相机
this.camera.position.x = 10.5;
this.camera.position.y = 32.3; // 设置相机的位置
this.camera.position.z = 104.3;
this.scene.add(this.camera); // 将相机添加到场景中
},
- 创建灯光
创建一个平行光和一个环境光
initLight() {
const light = new THREE.DirectionalLight(0xffffff); // 平行光
light.position.set(0.5, 1.0, 0.5).normalize(); // 设置平行光的方向,从(0.5, 1.0, 0.5)->target一般(0, 0, 0)
this.scene.add(light); // 将灯光添加到场景中
const ambLight = new THREE.AmbientLight(0xf0f0f0, 0.1); // 环境光
this.scene.add(ambLight);
},
- 创建渲染器
创建渲染器,并将渲染器节点添加到html中
initRenderer() {
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.outputEncoding = THREE.sRGBEncoding;
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth - 201, window.innerHeight);
document.getElementById("THREE49").appendChild(this.renderer.domElement);
},
- 创建轨道控制器
创建轨道控制器并设置控制器的焦点
initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.addEventListener("change", this.render);
this.controls.target.set(22, 26, -7); // 控制器的焦点
this.controls.update();
},
- 加载模型
加载【树】、【女孩】、【小狗】模型,并设置模型的缩放,让他们看起来和谐一点,然后将模型添加到场景中
initModel() {
this.gltfLoader.load(
"/models/models/gltf/urban_tree/scene.gltf",
(gltf) => {
gltf.scene.scale.set(10, 10, 10);
gltf.scene.position.set(40, 0, 0);
this.scene.add(gltf.scene);
}
);
this.gltfLoader.load("/models/models/gltf/shiba/scene.gltf", (gltf) => {
gltf.scene.scale.set(3, 3, 3);
gltf.scene.position.set(-5, 3, 1);
this.scene.add(gltf.scene);
});
this.gltfLoader.load("/models/models/gltf/matilda/scene.gltf", (gltf) => {
gltf.scene.scale.set(0.1, 0.1, 0.1);
this.scene.add(gltf.scene);
});
},
- 渲染场景和相机
在每次渲染的时候获取相机位置和获取控制器的焦点,先获取能聚焦物体的最合适的相机位置和控制器的焦点,然后写进按钮事件中,即可实现点击按钮聚焦到某物体。
render() {
console.log("this.camera.position", this.camera.position); // 获取相机位置
console.log("target", this.controls.target); // 获取控制器的焦点
this.renderer.render(this.scene, this.camera);
},
写在最后
以上就是所有的代码和说明。