threejs配合tween实现相机视角2D、3D的切换动画

这篇博客介绍了如何使用Three.js库创建3D场景,并实现相机视角在3D和2D之间的平滑切换。内容包括设置相机、场景、光源、渲染器和OrbitControls控制器,以及创建动画循环。通过ChangeControl方法和Tween模块,平滑地调整相机位置,以达到视角切换的效果。此外,还详细展示了不同视角下控制器的鼠标事件配置。
摘要由CSDN通过智能技术生成

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()
},
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值