【图片效果完整代码位于文章末】
1.项目开发引入threejs
本文档使用的是142版本
npm install three@0.142.0 --save
import * as THREE from 'three';
除核心THREE外,还有其他功能扩展库,位于examples/jsm目录下,例如相机控件OrbitControls、加载3d模型GLTFLoader等
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
2.基础场景创建
一个三维的场景以下几个对象:场景(scene)、相机(camera)和渲染器(renderer)
1.创建场景
const scene = new THREE.Scene();
2.创建相机
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set(0, 0, 5)//设置相机的位置
四个参数分别代表,视野角度(FOV)、长宽比(aspect ratio)、近截面(near)、远截面(far)
视野角度(FOV):FOV代表“Field of View”,即视场角,它决定了相机所能捕捉到的场景的垂直或水平视角范围。在透视投影中,通常指的是垂直视角,即从相机位置看去,上下边界与视椎体顶点连线形成的夹角。更大的FOV意味着更宽广的视野,可以看到更多的场景内容,但同时也会导致物体显得更小且透视效果更明显。
长宽比(Aspect Ratio): 这个参数描述的是相机视窗的宽度相对于高度的比例。在实际应用中,这通常是窗口或屏幕的宽度除以高度。保持正确的长宽比有助于确保场景中的物体不会变形,特别是在窗口大小改变时。例如,常见的显示器长宽比有16:9、4:3等。在设置相机投影矩阵时,正确设置此参数可以确保画面在不同尺寸的屏幕上正确拉伸或压缩,从而保持视觉上的正方形不变形。
近截面(Near Clipping Plane): 近截面是相机前方的一个虚拟平面,位于这个平面与相机之间的所有物体都会被剔除,不会显示在最终渲染的结果中。近截面距离相机越近,可渲染的最近物体就越靠近相机,但过近的距离可能导致深度精度问题(z-fighting),即非常接近近截面的物体可能会出现绘制错误。
远截面(Far Clipping Plane): 远截面则是相机前方另一个虚拟平面,位于这个平面之后的所有物体同样会被剔除,不参与渲染。设定合适的远截面距离可以提高渲染效率,因为超出这个范围的物体无需进行详细的计算。然而,如果远截面设置得过远,可能会降低深度缓冲区的有效精度,而设置得过近则可能使远处的场景无法正常显示。
3.创建渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
4.创建一个几何体
const geometry = new THREE.BoxGeometry(1, 1, 1) //立方体
const material = new THREE.MeshBasicMaterial({
color: 0xff00a2d7,//颜色
transparent: true, //开启透明
opacity: 0.5, //设置透明度
})
const cube = new THREE.Mesh(geometry, material)//创建方块实例对象
cube.position.set(0, 0, 0)
scene.add(cube)//将方块添加进场景
经过以上代码,我们获得了一个加载了正方体的场景
5.相机控制器
为了能够用鼠标控制场景相机位置,我们需要添加相机控制器OrbitControls
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const controls = new OrbitControls(camera, renderer.domElement)
controls.update()
这样我们就可以使用鼠标对立方体进行移动
6.添加动画
为了能让立方体自己动起来,我们可以添加一个动画函数,改变物体的位置position或旋转角度rotation。
function animate() {
requestAnimationFrame(animate)
controls.update()
cube.rotation.y += 0.01
renderer.render(scene, camera)
}
animate()
这样我们就得到了一个可以沿y轴旋转的立方体
完整代码如下
<template></template>
<script setup>
import * as THREE from 'three'
import { onMounted } from 'vue'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
onMounted(() => {
init()
})
function init() {
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
camera.position.set(0, 0, 5)
const renderer = new THREE.WebGLRenderer({ antialias: true }) //antialias抗锯齿
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({
color: 0xff00a2d7,
transparent: true,
opacity: 0.5,
})
const cube = new THREE.Mesh(geometry, material)
cube.position.set(0, 0, 0)
scene.add(cube)
const controls = new OrbitControls(camera, renderer.domElement)
controls.update()
function animate() {
requestAnimationFrame(animate)
controls.update()
cube.rotation.y += 0.01
renderer.render(scene, camera)
}
animate()
}
</script>