技术用到了
1. three 版本^0.156.1
2. dat.gui 版本 ^0.7.9 调试工具
3. gsap 版本 ^3.12.2 动画库
vue2 2.6.12
支持vue3
在src 文件夹 新建 three文件 index.js
说明 :
我是根据 原文链接 教你用three.js写一个炫酷的3D登陆页面 - 掘金 这位博主 的文件改版的 我也是刚接触 three没多久 有写的不好的 多多包含
我就不把我们的项目资料发出来了 需要的可以自己百度 或者找原来的博主里面拿
// 引入three.js
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
// 导入动画库
import gsap from "gsap";
// 导入dat.gui
import * as dat from "dat.gui";
let dirigible = null;
const LoginDom = (dom) => {
//创建一个三维场景
const scene = new THREE.Scene();
// 创建纹理加载器
const textureLoader = new THREE.TextureLoader();
// 导入纹理贴图基础贴图
const chungeLoader = textureLoader.load(
require("@/assets/images/earth_bg.png") // 地球的平面贴图
);
//创建一个圆物体(形状)
const geometry = new THREE.SphereGeometry(70, 70, 70); //长宽高都是80的圆形
//创建材质(外观)
const material = new THREE.MeshLambertMaterial({
// color: 0x0000ff,//设置材质颜色
transparent: true, //开启透明度
opacity: 0.8, //设置透明度
map: chungeLoader,
});
//创建一个网格模型对象
const mesh = new THREE.Mesh(geometry, material); //网络模型对象Mesh
// 组合对象 用于旋转
const Sphere_Group = new THREE.Group();
Sphere_Group.add(mesh);
Sphere_Group.position.x = -200;
Sphere_Group.position.y = 100;
Sphere_Group.position.z = 200;
scene.add(Sphere_Group);
const event = {};
event.onLoad = (e) => {
console.log("模型加载完成", e);
};
event.onProgress = (url, num, total) => {
console.log("模型加载进度的百分比", ((num / total) * 100).toFixed(2) + "%");
};
event.onError = (e) => {
console.log("模型加载失败", e);
};
// 设置加载管理器 模型 加载完成 失败 进度回调
const loadingManager = new THREE.LoadingManager(
event.onLoad,
event.onProgress,
event.onError
);
// 创建模型加载器 加入模型加载进度回调
let loader = new GLTFLoader(loadingManager);
// 加载模型
loader.load(
"xxx.glb",
(glft) => {
// 设置模型的位置
glft.scene.position.set(191.6, 61.556, -550.2);
dirigible = glft.scene;
scene.add(glft.scene);
// 更新相机位置
camera.position.set(300, 300, 300);
// 重新渲染
renderer.render(scene, camera);
// 进入动画
gsap.to(dirigible.position, {
x: 191.6,
y: 61.556,
z: -350.2,
duration: 1.5,
yoyo: true,
});
}
);
//添加平行光光源
const ambient = new THREE.AmbientLight(0xffffff, 0.4);
const light = new THREE.DirectionalLight(0xffffff, 2); //平行光源,color:灯光颜色,intensity:光照强度
scene.add(ambient);
// light.position.set(200, 300, 400);
scene.add(light);
//创建一个透视相机,窗口宽度,窗口高度
const width = window.innerWidth,
height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
//设置相机位置
camera.position.set(300, 300, 300);
//设置相机方向
camera.lookAt(0, 0, 0);
//创建辅助坐标轴
// const axesHelper = new THREE.AxesHelper(120); //参数200标示坐标系大小,可以根据场景大小去设置
// scene.add(axesHelper);
//创建一个WebGL渲染器
// 背景色变透明
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setClearAlpha(0.1);
renderer.setSize(width, height); //设置渲染区尺寸
renderer.render(scene, camera); //执行渲染操作、指定场景、相机作为参数
// const controls = new OrbitControls(camera, renderer.domElement); //创建控件对象
const controls = new OrbitControls(camera, renderer.domElement); //创建控件对象
// 设置控制器阻尼 让控制器更有真实效果 必须在动画循环里调用.update()
controls.enableDamping = false;
//是否可以缩放
controls.enableZoom = false;
//是否自动旋转
controls.autoRotate = false;
//设置相机距离原点的最远距离
controls.minDistance = 1;
//设置相机距离原点的最远距离
// controls.maxDistance = 500;
//是否开启右键拖拽
controls.enablePan = false;
// 是否可以旋转
controls.enabled = true;
dom.appendChild(renderer.domElement); // 将数据传递到界面
// 设置时钟
const clock = new THREE.Clock();
// 根据浏览器每一帧渲染
const render = () => {
let time = clock.getElapsedTime();
controls.update();
renderer.render(scene, camera);
Sphere_Group.rotateY(0.001);
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render);
};
render();
window.addEventListener("mouseup", () => {
// 鼠标失去点击焦点 恢复相机初始位置
camera.position.set(300, 300, 300);
});
// 监听画面变化, 更新渲染画面
window.addEventListener("resize", () => {
console.log("画面变化了");
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 更新设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
};
//登录调用的方法
const modelLogin = (callback) => {
// 执行动画脚本 动画结束后执行回调 进入登录界面
gsap.to(dirigible.position, {
x: -300,
y: 20,
z: 150,
duration: 1.5,
yoyo: true,
});
gsap.to(dirigible.scale, {
x: 0.0001,
y: 0.0001,
z: 0.0001,
duration: 1.5,
yoyo: true,
onComplete: () => {
console.log("动画完成");
callback(true);
},
});
gsap.to(dirigible.rotation, {
x: 0.04,
y: -1,
z: 0,
// z: -0.59,
duration: 1,
yoyo: true,
// repeat: -1,
});
};
export { LoginDom, modelLogin };
<template>
<div class="login">
// three 容器
<div ref="login_three" id="login-three-container"></div>
</div>
</template>
<script>
import { LoginDom, modelLogin } from "@/three";
export default {
name: "Login",
data() {
return {
};
},
mounted() {
// 将容器传到three 上
LoginDom(this.$refs.login_three);
},
methods: {
login () {
function f(param) {
// 如果为true 执行跳转逻辑
if (param) {
// 跳转到首页或者其他界面
}
}
// 执行模型飞行动画
modelLogin(f);
}
},
};
</script>
<style rel="stylesheet/scss" lang="scss">
</style>