第一步导入three,和轨道控制器
// 导入three
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
第二步创建场景,相机,设置相机位置,场景中添加相机。
// 1、创建场景
const scene = new THREE.Scene();
// 2、创建相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机位置
camera.position.set(0,10, 10);
// 场景中添加相机
scene.add(camera);
第三步创建几何体,材质合成物体,设置位置,场景中添加物体,还能设置物体的放大,旋转
// 添加物体
// 创建几何体
const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
// 根据几何体和材质创建物体
const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(0,0,0);
// 将几何体添加到场景中
scene.add(cube);
// 放大
cube.scale.set(1, 1, 1);
// 旋转
cube.rotation.x = -Math.PI/2
物体构建有点模型Points、线模型Line、网格模型Mesh,三种
第四步,初始化渲染器,设置渲染器大小,将渲染器的画面绑定到页面中
// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);
第五步,创建轨道控制器,监听鼠标的拖动,时时渲染页面
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
function render() {
// 使用渲染器,通过相机将场景渲染进来
renderer.render(scene, camera);
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render);
}
render();
副助功能:
1.跟踪事件处理动画
const clock = new THREE.Clock();
function render() {
// 获取自时钟启动后的秒数。
let time = clock.getElapsedTime();
// console.log("时钟运行总时长:", time);
//let deltaTime = clock.getDelta();
//console.log("两次获取时间的间隔时间:", deltaTime);
let t = time % 5;
cube.position.x = t * 1;
// 使用渲染器,通过相机将场景渲染进来
renderer.render(scene, camera);
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render);
}
2.导入动画库(单独动画,和组合动画)
// 导入动画库
import gsap from "gsap";
//物体单独的动画
gsap.to(
cube.rotation,
{
x: 2 * Math.PI, //x轴旋转360
duration: 5, //时间几秒
ease: "power1.inOut" //运动方式
}
);
//物体的组合动画(x轴来回移动,加旋转)
// 设置动画
var animate1 = gsap.to(cube.position, {
x: 5,
duration: 5,
ease: "power1.inOut",
// 设置重复的次数,无限次循环-1
repeat: -1,
// 往返运动
yoyo: true,
// delay,延迟2秒运动
delay: 2,
onComplete: () => {
console.log("动画完成");
},
onStart: () => {
console.log("动画开始");
},
});
gsap.to(cube.rotation, { x: 2 * Math.PI, duration: 5, ease: "power1.inOut" });
// 鼠标双击事件
window.addEventListener("dblclick", () => {
// isActive判断动画的状态
if (animate1.isActive()) {
// 进行动画暂停
animate1.pause();
} else {
// 进行动画恢复
animate1.resume();
}
});
3,控制场景全屏,和退出全屏
window.addEventListener("dblclick", () => {
const fullScreenElement = document.fullscreenElement;
if (!fullScreenElement) {
// 双击控制屏幕进入全屏,退出全屏
// 让画布对象全屏
renderer.domElement.requestFullscreen();
} else {
// 退出全屏,使用document对象
document.exitFullscreen();
}
});
4.自适应屏幕大小
// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {
// console.log("画面变化了");
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
5.创建物体(包含)
//BoxGeometry盒子几何体长宽高
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
//SphereGeometry球面几何体 半径 ,水平分段数,竖直分段数
const geometry = new THREE.SphereGeometry( 15, 32, 16 );
const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
const sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
//PlaneGeometry平面缓冲几何体(平面)
const geometry = new THREE.PlaneGeometry( 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
const plane = new THREE.Mesh( geometry, material );
scene.add( plane );
//CircleGeometry圆形缓冲几何体(圆面,没有背面)
const geometry = new THREE.CircleGeometry( 5, 32 );
const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
const circle = new THREE.Mesh( geometry, material );
scene.add( circle );
//ConeGeometry圆锥缓冲几何体 半径,高度,底部面数
const geometry = new THREE.ConeGeometry( 5, 20, 32 );
const material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
const cone = new THREE.Mesh( geometry, material );
scene.add( cone );
//CylinderGeometry圆柱缓冲几何体 顶部半径,底部半径,高度,光滑成都
const geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );
const material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
const cylinder = new THREE.Mesh( geometry, material );
scene.add( cylinder );
//DodecahedronGeometry十二面缓冲几何体
const radius = 7; // ui: radius
const geometry = new THREE.DodecahedronGeometry(radius);
//EdgesGeometry边缘几何体
const geometry = new THREE.BoxGeometry( 100, 100, 100 );
const edges = new THREE.EdgesGeometry( geometry );
const line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
scene.add( line );
6.材质
MeshBasicMaterial 不受光照的影响。
MeshLambertMaterial 只在顶点计算光照,
而 MeshPhongMaterial 则在每个像素计算光照, 还支持镜面高光。
const material = new THREE.MeshPhongMaterial({
color: 0xFF0000, // 红色 (也可以使用CSS的颜色字符串)
flatShading: true,
});
//另一种材质
const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000}); // 红色
const m2 = new THREE.MeshBasicMaterial({color: 'red'}); // 红色
const m3 = new THREE.MeshBasicMaterial({color: '#F00'}); // 红色
const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'}); // 红色
const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)'});
7,加载纹理
const loader = new THREE.TextureLoader();
const texture = loader.load('resources/images/flower-1.jpg');
8,加载模型
import {OBJLoader} from '/examples/jsm/loaders/OBJLoader.js';
const objLoader = new OBJLoader();
objLoader.load('resources/models/windmill/windmill.obj', (root) => {
scene.add(root);
});
9,物体产生阴影(移动阴影贴图,有三种光可以投射阴影,分别为DirectionalLight 定向光、SpotLight 聚光灯,)
//告诉渲染器显示阴影贴图;
renderer.shadowMap.enabled = true;
//对需要投影的物体设置castShadow为true;
sphere.castShadow = true;
//对需要接收投影的物体设置receiveShadow为true;
plane.receiveShadow = true;
//最后,对可以产生阴影的光源设置castShadow为true;
light.castShadow = true;
10,光源
//1,环境光THREE.AmbientLight
颜色会应用到全局,该光源没有特别的来源方向,也不会产生阴影。通常,该光源不是场景中的唯一光源,因为它会将场景中的所有物体渲染为相同的颜色,它通常与其他光源同时使用,目的是弱化阴影或给场景中添加额外的颜色。使用该光源需要注意,着色一定要趋于保守,否则场景的颜色会过于饱和或者昏暗。
const AmbientLight = new THREE.AmbientLight('#606008')
scene.add(AmbientLight)
//2,THREE.SpotLight聚光灯光源,是我们经常使用的光源之一。
该光源,是一种具有锥形光源的效果,你可以把它当作手电筒或者灯塔一样,该光源具有方向和角度。
const spotLight = new THREE.SpotLight(0xFFFFFF)
spotLight.position.set(-40, 40, -15)
spotLight.castShadow = true
spotLight.shadow.mapSize = new THREE.Vector2(1024, 1024)
spotLight.shadow.camera.far = 130
spotLight.shadow.camera.near = 40
spotLight.distance = 0
spotLight.target = plane
spotLight.angle = 0.4
spotLight.shadow.camera.fov = 120
scene.add(spotLight)
如何让聚光灯指向某个点呢?
const target = new THREE.Object3D()
target.position = new THREE.Vector(5, 0, 0)
spotLiht.target = target
//3,THREE.PointLight点光源,是一种单点发光,照射所有方向的光源。
点光源也有一些属性:
const pointLigh = new THREE.PointLight('#ccffcc')
pointLigh.dispose = 100
pointLigh.position.set(3, 0, 10)
scene.add(pointLigh)
//4,THREE.HemisphereLight是一种特殊光源,它被称为自然光。因为大自然的光线很复杂,有的来自物体的折射等等,很难模拟。所以,THREE.HemisphereLight 的出现,很好的解决了这一问题。
// 自然光
const hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00f00, 0.6)
hemiLight.position.set(0, 500, 0)
scene.add(hemiLight)
//5. THREE.AreaLight
定义一个长方形发光区域。
const areaLight = new THREE.AreaLight(0xff0000, 500, 4, 10)
areaLight.position.set(-10, 10, -35)
scene.add(areaLight)
该对象三个参数为 颜色、光强度、宽度、高度。
//6,镜头光晕
当你对着太阳,或者非常明亮的光源拍照时,会出现镜头光晕。当然,Three.js 也支持这样的效果。首先,我们需要创造镜头光晕的对象。
import Lensflare from 'three/examples/jsm/objects/Lensflare'
const lensflare = new Lensflare(texture, size, distance, color)
补充详情,总结
2. THREE.SpotLight