1.所需依赖
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
import {TWEEN} from "three/examples/jsm/libs/tween.module.min";
2.基础功能:相机、场景、光源、渲染器、控制器
//data
threejs: { //threejs组件
camera: null,
scene: null,
renderer: null,
controls: null,
animateId: null,
},
ControlsType:"3D",
//创建相机
initCamera() {
this.threejs.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000)
this.threejs.camera.position.set(40, 40, 40); //相机位置
},
//创建场景
initScene() {
this.threejs.scene = new THREE.Scene()
this.threejs.scene.background = new THREE.Color("#353F47");
this.threejs.scene.add(this.threejs.camera)
},
//光源
initLight() {
//环境光
const ambientLight = new THREE.AmbientLight("#ffffff", 1);
this.threejs.scene.add(ambientLight);
//平行光
const directionalLight = new THREE.DirectionalLight("#555e66", 1);
directionalLight.position.set(20, 40, -40);
this.threejs.scene.add(directionalLight);
},
//渲染器
initRenderer() {
this.container = document.getElementById('container')
this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
this.renderer.setPixelRatio(this.container.devicePixelRatio);
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
this.container.appendChild(this.renderer.domElement)
this.threejs.renderer.shadowMap.enabled = true; //阴影效果
},
//视图控制器
initControls() {
this.threejs.controls = new OrbitControls(this.threejs.camera, this.threejs.renderer.domElement);
this.threejs.controls.maxPolarAngle = 1.5;//上下翻转的最大角度
this.threejs.controls.minPolarAngle = 0;//上下翻转的最小角度
this.threejs.controls.enableZoom = true;//是否允许缩放
this.threejs.controls.enableDamping = true //控制是否带有惯性
// this.threejs.controls.autoRotate = true //自动围绕中心旋转
},
3.animate循环动画
animate() {
this.animateId = requestAnimationFrame(this.animate);
this.threejs.renderer.render(this.threejs.scene, this.threejs.camera);
this.threejs.controls.update();
//判断相机模式
if (this.ControlsType === "3D") {
this.threejs.controls.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.ZOOM,
RIGHT: THREE.MOUSE.PAN
}
} else if (this.ControlsType === "2D") {
this.threejs.controls.mouseButtons = { //控制器的鼠标事件替换为平移和缩放
LEFT: THREE.MOUSE.PAN,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
}
}
TWEEN.update();
},
4.切换时调用方法ChangeControl
ChangeControl(flag){
this.ControlsType = flag
if(this.ControlsType === "2D"){
this.tween2D({
x:0,y:0,z:0
})
}else{
this.threejs.controls.reset() //将控制器重置为初始状态,重置平移后的中心点
this.tween3D({
x:20,y:20,z:20
})
}
},
tween3D(Position) { //传递任意目标位置,从当前位置运动到目标位置
if(this.ControlsType === "3D"){
let that = this
this.threejs.camera.lookAt(new THREE.Vector3(0, 0, 0));
var p1 = { //定义相机位置是目标位置到中心点距离的2.2倍
x:this.threejs.camera.position.x / 2.2,
y:this.threejs.camera.position.y - 15,
z:this.threejs.camera.position.z / 2.2
}
var p2 = {
x: Position.x,
y: Position.y,
z: Position.z,
}
var tween = new TWEEN.Tween(p1).to(p2, 1200);//第一段动画
var update = function (object) {
that.threejs.camera.position.set(object.x * 2.2, object.y + 15, object.z * 2.2);
that.threejs.camera.lookAt(0, 0, 0); //保证动画执行时,相机焦距在中心点
that.threejs.controls.enabled = false;
that.threejs.controls.update();
};
tween.onUpdate(update);
// 动画完成后的执行函数
tween.onComplete(() => {
that.threejs.controls.enabled = true; //执行完成后开启控制
});
tween.easing(TWEEN.Easing.Quadratic.InOut);
tween.start();
}
},
tween2D(Position) { //传递平面展示的中心位置,x:0,y:0,z:0。将相机视角切换到中心位置的正上方
let that = this
this.threejs.camera.lookAt(new THREE.Vector3(0, 0, 0));
var p1 = {
x:this.threejs.camera.position.x,
y:this.threejs.camera.position.y - 40,
z:this.threejs.camera.position.z
}
var p2 = {
x: Position.x,
y: Position.y,
z: Position.z,
}
var tween = new TWEEN.Tween(p1).to(p2, 1200);//第一段动画
var update = function (object) {
that.threejs.camera.position.set(object.x, object.y + 40, object.z);
that.threejs.camera.lookAt(0, 0, 0); //保证动画执行时,相机焦距在中心点
that.threejs.controls.enabled = false; //执行动画时禁止控制
that.threejs.controls.update();
};
tween.onUpdate(update);
// 动画完成后的执行函数
tween.onComplete(() => {
that.threejs.controls.enabled = true; //执行完成后开启控制
});
tween.easing(TWEEN.Easing.Quadratic.InOut);
tween.start();
},
5.初始化方法
init() {
this.initRenderer()
this.initCamera()
this.initScene()
this.initLight()
this.initControls()
},
mounted() {
this.init()
this.animate()
},