学习地址
官方网站,可切换中文查看
普通环境搭建
在HTML文件的中引入threejs的CDN即可:BootCDN
可以测试是否引入成功
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/r134/three.min.js"></script>
console.log('当前使用Threejs版本:' + window.__THREE__);
NPM环境搭建
先对某文件夹进行npm init
初始化,然后安装parceljs打包工具,命令为npm i parcel
,然后创建html入口并指定为打包目录
"scripts": {
"dev": "parcel src/index.html",
"build": "parcel build src/index.html"
},
指定样式文件和js入口文件
<link rel="stylesheet" href="./assets/css/style.css">
<script src="./assets/js/main.js" type="module"></script>
环境就搭建好了
安装Three
npm i three
引入
import * as THREE from 'three'
Three基础流程
import * as THREE from 'three'
import {
OrbitControls
} from 'three/examples/jsm/controls/OrbitControls'
// console.log(THREE);
// 创建场景
const scene = new THREE.Scene()
// 创建透视相机:视野角度、长宽比、近端面、远端面
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
// 调整相机位置
camera.position.set(5, 5, 5)
// 或者 camera.position.x = 5
// 把相机加入场景
scene.add(camera)
// 添加几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 材质
const material = new THREE.MeshBasicMaterial({
color: 0x4194cd
});
// 根据几何体和材质创建网格
const cube = new THREE.Mesh(geometry, material);
// 设置角度
cube.rotation.set(0.5, 0.5, 0)
// 加入场景
scene.add(cube);
// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 将内容添加到body
document.body.appendChild(renderer.domElement)
// 使用渲染器将相机、场景进行渲染
// renderer.render(scene, camera)
// 创建轨道控制器:指定相机和渲染器
const controls = new OrbitControls(camera, renderer.domElement)
// 每帧重渲染
function render() {
renderer.render(scene, camera)
requestAnimationFrame(render)
}
render()
坐标辅助器
能更方便开发时进行查看
// 添加坐标轴辅助器,指定长度
const axesHelper = new THREE.AxesHelper(5)
// 加入场景
scene.add(axesHelper)
轨道控制器
// @ts-ignore
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement)
// 禁止缩放
controls.enableZoom = false
// 禁止旋转
controls.enableRotate = false
物体的位置和移动
// 添加几何体及其大小
const geometry = new THREE.BoxGeometry(1, 1, 1);
// 材质及颜色
const material = new THREE.MeshBasicMaterial({
color: 0x4194cd
});
// 根据几何体和材质创建网格对象
const cube = new THREE.Mesh(geometry, material);
// 设置物体配置
cube.position.set(0, 0, 0)
// 或者直接设置单一位置
// cube.position.x = 1
// 加入场景
scene.add(cube);
// 每帧重渲染
function render() {
cube.position.x += 0.01
if (cube.position.x > 5) {
cube.position.x = 0
}
renderer.render(scene, camera)
requestAnimationFrame(render)
}
物体缩放和旋转
// 缩放
// cube.scale.set(2, 1, 1)
// 或者
cube.scale.x = 3
// 旋转
cube.rotation.set(Math.PI / 8, 0, 0)
// 一直旋转
cube.rotation.x += 0.01
requestAnimationFrame卡顿问题
requestAnimationFrame是尽可能的接近1帧的时间,但是受到电脑性能的影响,肯能出现跳帧的情况,所以在计算的时候最好使用帧的时间计算动画
// 时钟运行时长
let time = clock.getElapsedTime()
// 下一次获取间隔时间
let deltaTime = clock.getDelta()
console.log('运行时长' + time)
console.log('获取间隔' + deltaTime)
阻尼
解决控制器的晃动问题
// 创建轨道控制器:指定相机和渲染器
const controls = new OrbitControls(camera, renderer.domElement)
// 开启阻尼
controls.enableDamping = true
// 每帧重渲染
function render() {
controls.update()
renderer.render(scene, camera)
requestAnimationFrame(render)
}
平面几何体及可反射光线的Lamber材质
// 平面几何体(指定高度、宽度)
let planeGeometry = new THREE.PlaneGeometry(10, 10)
// 指定为可反射光线的Lamber材质
let planeLambertMaterial = new THREE.MeshLambertMaterial({
color: 0x888888
})
// 根据几何体和材质创建网格
let plane = new THREE.Mesh(planeGeometry, planeLambertMaterial)
// 设置位置
plane.rotation.x = -0.5 * Math.PI
// 加入场景
scene.add(plane)
AmbientLight光源
该光源应用到整个场景中,没有特殊来源方向,不会产生阴影
// 加入AmbientLight光源,该光源应用到整个场景中,没有特殊来源方向,不会产生阴影
let ambientLight = new THREE.AmbientLight(0xaaaaaa)
// 加入场景
scene.add(ambientLight)
聚光灯光源与投影
// 投影光源,聚光灯光源
let spotLight = new THREE.SpotLight(0xffffff)
// 设置聚光灯位置
spotLight.position.set(10, 10, -10)
// 开启阴影
spotLight.castShadow = true
// 设置阴影效果
spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024)
spotLight.shadow.camera.far = 20
spotLight.shadow.camera.near = 10
// 加入场景
scene.add(spotLight)
然后给平面加上接受阴影属性
// 接受阴影
plane.receiveShadow = true
给渲染器加上阴影渲染
// 开启阴影渲染
renderer.shadowMap.enabled = true
给物体加上阴影属性,注意要使用MeshLambertMaterial材质
// 开启阴影
cube.castShadow = true
画面自适应和全屏
解决当容器大小变化后无法自适应问题
// 自适应
window.addEventListener('resize', () => {
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight
// 更新摄像头投影矩阵
camera.updateProjectionMatrix()
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight)
// 更新渲染器像素比
renderer.setPixelRatio(window.devicePixelRatio)
})
全屏
// 全屏(非网页,而是指定元素)
window.addEventListener('dblclick', () => {
if (document.fullscreenElement) {
document.exitFullscreen()
} else {
renderer.domElement.requestFullscreen()
}
})
物体移除
scene.remove(cube)
圆环
// 圆环 参数:半径 粗线 分段 圆润
let torusGeometry = new THREE.TorusGeometry(0.5, 0.2, 70, 100)
// 材质
const torusGeometryMaterial = new THREE.MeshLambertMaterial({
color: 0xff2288
});
// 根据几何体和材质创建网格
const torus = new THREE.Mesh(torusGeometry, torusGeometryMaterial);
// 设置位置
torus.position.set(3, 1, -2)
// 开启阴影
torus.castShadow = true
// 加入场景
scene.add(torus);
柱体
// 柱体 参数 顶部半径 底部半径 高度 分段数 高度分段数 地面是否开放
let cylinderGeometry = new THREE.CylinderGeometry(0.8, 0.8, 1.2, 100)
// 材质
const cylinderGeometryMaterial = new THREE.MeshLambertMaterial({
color: 0x4194cd
});
// 根据几何体和材质创建网格
const cylinder = new THREE.Mesh(cylinderGeometry, cylinderGeometryMaterial);
// 设置位置
cylinder.position.set(3, 1, -2)
// 开启阴影
cylinder.castShadow = true
// 加入场景
scene.add(cylinder);
球体
const geometry = new THREE.SphereGeometry(1, 100, 100);
贴图
let textureLoader = new THREE.TextureLoader()
let texture = textureLoader.load('/zhuan.png')
material.map = texture
导入glb模型
import {
GLTFLoader
} from 'three/examples/jsm/loaders/GLTFLoader'
// 加载模型
let loader = new GLTFLoader()
loader.load('/other.glb', function (gltf) {
scene.add(gltf.scene)
gltf.scene.position.set(0, 2, 0)
})
注意加载模型的位置
环境贴图
用户给物体的周围制造环境
// 加入环境贴图
scene.background = new THREE.CubeTextureLoader().setPath('/').load(['2.png', '2.png', '2.png', '2.png', '2.png', '2.png'])
注意,图片的宽高要一样,如果需要物体根据贴图反光,需要给物体加上envMap
// 材质
const material = new THREE.MeshLambertMaterial({
color: 0xffffff,
envMap: scene.background
});