three.js的使用
以创建一个立方体为例
安装
安装three:npm i three
使用
引用
引入three以及three中自带的相机控件OrbitControls用以操控相机:
初始化场景
scene:场景所有three事物均在其中。
camera:使用PerspectiveCamera透视相机,参数需注意调整否则会看不见物体与场景,参数依次为:fov视场,即可看到的角度范围,aspect长宽比,通常为窗口长宽比,near近面,基于相机位置开始渲染场景的位置一般较小默认0.1,far远面,基于相机位置结束渲染场景的位置,过大会影响渲染效率默认1000。
renderer:渲染器,用于生成canvas及设置其参数,需要将其appendChild至dom中指定元素。
天空盒子
创建天空盒子(一个包裹场景物体的立方体,可随鼠标拖动而变化角度),其中六张立方体贴图对应的顺序是右、左、上、下、前、后,图片需是特别制作的全景图,否者场景世界会出现明显的拼接边角:
也可直接使用一张贴图作为场景的背景,但使用此法场景不会随着鼠标变换角度与缩放:
相机控件
创建相机控件,其中需将相机与渲染的canvas元素添加到控件OrbitControls中,可通过控件控制拖拽、缩放、阻尼、偏角、自转(此种自转方式区别于模型自转,模型自转是通过控制物体mesh的rotation实现自转,该文章使用的是模型自转)等:
光源
创建光源,可设置环境光、点光源,最终显示出的光影效果是通过各种光效一起计算后渲染出来的:
立方体
创建的mesh(可理解为创建的物体)都是要通过add添加到场景中的,而mesh中有geometry(几何体)与material(材质),立方体的geometry可以利用three的BoxGeometry,而material可以使用MeshLambertMaterial材质,该材质对光照有反应,用于创建暗淡的不发光的物体,自身可设置颜色,自身颜色不受环境的影响。也可给材质设置纹理map(需导入图片作为纹理):
持续渲染
对场景与相机进行持续渲染,其中requestAnimationFrame为请求动画帧,以60hz刷新(但在高刷新屏中会频繁触发),用户切换标签时会暂停渲染,节省cpu开销。鼠标控件需要在渲染中调用update()更新:
完整代码
点击查看代码
<template> <div class="three-div"> <div id="container"> <!--画布的容器--> </div> </div> </template> <script> import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; //鼠标控制 import cubeImg from "@/assets/img/cube.png"; import BgImg from "@/assets/img/bg.png"; import right from "@/assets/img/space/right.jpg"; import left from "@/assets/img/space/left.jpg"; import top from "@/assets/img/space/top.jpg"; import bottom from "@/assets/img/space/bottom.jpg"; import front from "@/assets/img/space/front.jpg"; import back from "@/assets/img/space/back.jpg"; export default { components: {}, data() { return { scene: "", //场景 camera: "", //相机 renderer: "", //渲染器 mouseControls: "", //轨道控制 pointLight: "", //点光源 ambientLight: "", //环境光 cube: "", //立方体 cubeImg: cubeImg, //立方体贴图 }; }, mounted() { this.init(); }, methods: { //初始化场景 init() { this.scene = new THREE.Scene(); //新建场景 let width = window.innerWidth; //窗口宽度 let height = window.innerHeight; //窗口高度 let k = width / height; //窗口宽高比 this.camera = new THREE.PerspectiveCamera(60, k, 0.1, 10); //透视相机 this.camera.position.set(0, 0, 2.5); //设置相机位置 //创建渲染器 this.renderer = new THREE.WebGLRenderer({ antialias: true, //抗锯齿 alpha: true, }); this.renderer.setSize(width, height); //设置渲染区域尺寸 document .getElementById("container") .appendChild(this.renderer.domElement); //将画布添加到container中 let axes = new THREE.AxesHelper(1); //坐标系(辅助开发) axes.rotation.x = 0.1; // this.scene.add(axes); this.createSkyBox(); // this.createUniverse(); this.createOrbitControls(); this.createLight(); this.createCube(); this.repeatRender(); }, //创建天空盒子 createSkyBox() { //加载天空盒子纹理 let cubeTexture = new THREE.CubeTextureLoader().load( [right,left,top,bottom,front,back] ); this.scene.background = cubeTexture; //设置场景背景 }, //创建宇宙背景 createUniverse(){ let texture = new THREE.TextureLoader().load(BgImg);//加载背景贴图 this.scene.background = texture;//设置场景背景 }, //创建轨道控制 createOrbitControls() { //没有缩放阻尼 this.mouseControls = new OrbitControls( this.camera, this.renderer.domElement ); //创建控件对象 this.mouseControls.enablePan = false; //右键平移拖拽 this.mouseControls.enableZoom = true; //鼠标缩放 this.mouseControls.minDistance = 2; //相机距离原点的距离范围 this.mouseControls.maxDistance = 5; this.mouseControls.enableDamping = true; //滑动阻尼 this.mouseControls.dampingFactor = 0.1; //(默认.25) this.mouseControls.maxPolarAngle = (Math.PI / 4) * 3; //y旋转角度范围 this.mouseControls.minPolarAngle = Math.PI / 4; // this.mouseControls.autoRotate = true; //自转(相机) // this.mouseControls.autoRotateSpeed = 5; //自转速度 }, //创建光源 createLight() { this.ambientLight = new THREE.AmbientLight(0x666666); //设置环境光 this.scene.add(this.ambientLight); //将环境光添加到场景中 this.pointLight = new THREE.PointLight(0xffffff, 1, 0); this.pointLight.position.set(200, 200, 200); //设置点光源位置 this.scene.add(this.pointLight); //将点光源添加至场景 }, //创建立方体 createCube() { let geometry = new THREE.BoxGeometry(1, 1, 1); //几何体 //材质 let material = new THREE.MeshLambertMaterial({ map: new THREE.TextureLoader().load(this.cubeImg), //导入图片纹理 }); this.cube = new THREE.Mesh(geometry, material); //将几何体与材质添加到网格中 this.cube.rotation.set(10, 10, 0); this.scene.add(this.cube); //将立方体网格添加到场景中 }, //重复渲染 repeatRender() { //请求动画帧,屏幕每刷新一次调用一次,绑定屏幕刷新频率 requestAnimationFrame(this.repeatRender); this.mouseControls.update(); //实时更新轨道控制 this.cube.rotation.y += .01;//以y为轴心的旋转角度每帧自加0.01 this.renderer.render(this.scene, this.camera); //将场景和相机进行渲染 }, }, }; </script> <style scoped> </style>
图片素材
天空盒子贴图
back.jpg:
bottom.jpg:
front.jpg:
left.jpg:
right.jpg:
top.jpg:
立方体贴图
cube.png:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!