持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
写在前面
本文用vue+threejs控制相机绕轴旋转。
下面是界面效果图,按钮控制旋转,可以根据需求旋转固定的弧度或角度:
代码说明
- html和css
一个id="THREE46"的容器,用于添加渲染器节点,一个控制是否开启绕轴旋转的按钮
<template>
<div class="item">
<div id="THREE46">
<div class="buttons">
<el-button type="primary" @click="clickAutoRotate"
>{{
this.controls && this.controls.autoRotate ? "停止" : "开始"
}}绕轴旋转</el-button
>
<el-button type="primary">水平旋转角度:{{ AzimuthalAngle }}</el-button>
</div>
</div>
</div>
</template>
.buttons {
position: absolute;
top: 20px;
right: 20px;
}
- 引入threejs
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
- data()中定义的变量
camera相机,scene场景,dracoLoader模型加载器,renderer场景渲染器,controls轨道控制器,AzimuthalAngle物体当前旋转的角度值
data() {
return {
camera: null,
scene: null,
dracoLoader: null,
renderer: null,
controls: null,
AzimuthalAngle: 0,
};
},
- mounted()方法
mounted() {
this.dracoLoader = new DRACOLoader();
this.dracoLoader.setDecoderPath("js/libs/draco/");
this.dracoLoader.setDecoderConfig({ type: "js" });
this.initScene(); // 创建场景
this.initCamera(); // 创建相机
this.initLight(); // 创建灯光
this.initRenderer(); // 创建渲染器
this.initControls(); //创建轨道控制器
this.initGround(); // 创建地面
this.initModel(); // 加载模型
},
- initScene()
创建场景,并设置场景背景颜色
initScene() {
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x000000); // 设置场景背景颜色
},
- initCamera()
创建一个透视相机PerspectiveCamera
initCamera() {
this.camera = new THREE.PerspectiveCamera(
35,
(window.innerWidth - 201) / window.innerHeight,
1,
500
); // 透视相机
this.camera.position.x = 0.5;
this.camera.position.y = 0.5; // 设置相机的位置
this.camera.position.z = 1.8;
this.scene.add(this.camera); // 将相机添加到场景中
},
- initLight()
创建灯光,创建一个平行光DirectionalLight和一个环境光AmbientLight
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);
},
- initRenderer()
创建场景渲染器,并将渲染器节点插入到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("THREE46").appendChild(this.renderer.domElement);
},
- initControls()
创建轨道控制器,传入两个参数,一个是要控制的相机,一个是要控制的场景渲染器
在这里开启旋转this.controls.autoRotate = true;, 并设置旋转的速度为3this.controls.autoRotateSpeed = 3;
initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.addEventListener("change", this.render);
this.controls.enableDamping = true; // 开启惯性
this.controls.autoRotate = true;
this.controls.autoRotateSpeed = 3;
},
- initGround()
创建一个1x1的地面,并设置地面接收阴影ground.receiveShadow = true;
initGround() {
const ground = new THREE.Mesh(
new THREE.BoxGeometry(1, 0.0015, 1),
new THREE.MeshPhongMaterial({
color: 0x999999,
depthWrite: false,
transparent: true,
opacity: 1,
})
);
ground.receiveShadow = true;
this.scene.add(ground);
},
- initModel()
加载模型,使用dracoLoader加载器加载模型
initModel() {
this.dracoLoader.load("/models/models/draco/bunny.drc", (geometry) => {
geometry.computeVertexNormals();
const material = new THREE.MeshStandardMaterial({
color: 0xffffff,
});
let mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.y = -0.035;
this.scene.add(mesh);
this.dracoLoader.dispose();
this.animate();
});
},
- animate()和render()方法
在这里对旋转角度AzimuthalAngle进行赋值
render()方法中调用渲染器方法渲染场景和相机
animate() {
requestAnimationFrame(this.animate);
this.controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
// console.log("水平旋转角度", this.controls.getAzimuthalAngle());
// console.log("垂直旋转角度", this.controls.getPolarAngle());
this.AzimuthalAngle = (
(this.controls.getAzimuthalAngle() * 180) /
Math.PI
).toFixed(2);
this.render();
},
render() {
this.renderer.render(this.scene, this.camera);
},
- clickAutoRotate()
控制是否开启旋转的按钮的方法
clickAutoRotate() {
this.controls.autoRotate = !this.controls.autoRotate;
},
写在最后
以上就是所有的代码和说明。