Three.js 是基于 WebGL 技术,用于浏览器中开发 3D 交互场景的 JS 引擎。
默认 WebGL 只支持简单的 点、线、三角,Three.js 就是在此 WebGL 基础之上,封装出强大且使用起来简单的 JS 3D 类库。
目前主流现代浏览器都已支持 WebGL,也意味着支持 Three.js。
🔍 3D 可视化:Three.js 可以用于创建各种 3D 可视化应用,如数据可视化、科学可视化、工程可视化等。用户可以通过浏览器在线查看和操作 3D 模型,而无需安装任何插件或额外的软件。
🔍 虚拟现实和增强现实:Three.js 可以用于创建虚拟现实(VR)和增强现实(AR)应用,如游戏、教育、培训、设计等。用户可以通过 VR 设备和 AR 设备在 3D 空间中浏览和操作 3D 模型,获得更加沉浸式的体验。
🔍 动画和特效:Three.js 可以用于创建各种 3D 动画和特效,如电影、电视、游戏、广告等。用户可以通过浏览器在线观看和互动 3D 动画和特效,而无需安装任何插件或额外的软件。
🔍 游戏开发:Three.js 可以用于创建各种 3D 游戏,如角色扮演游戏、射击游戏、策略游戏等。用户可以通过浏览器在线玩 3D 游戏,而无需安装任何插件或额外的软件。
🔍 产品展示和演示:Three.js 可以用于创建各种 3D 产品展示和演示,如家具、汽车、电子产品等。用户可以通过浏览器在线查看和操作 3D 模型,了解产品的外观、性能和功能,提高购买决策的准确性。
🔍 建筑和城市规划:Three.js 可以用于创建各种 3D 建筑和城市规划应用,如房地产开发、城市规划、景观设计等。用户可以通过浏览器在线查看和操作 3D 模型,了解项目的设计理念和实施效果,提高决策的准确性。
场景是 Three.js 中的一个核心概念,它是所有 3D 对象的容器。场景可以包含几何体、光源、相机等,它们共同构成了一个完整的 3D 世界。在 Three.js 中,场景是通过 THREE.Scene
类来表示的。
相机是 Three.js 中的另一个核心概念,它负责捕捉 3D 世界中的对象,并将它们渲染到屏幕上。Three.js 提供了多种相机类型,如正交相机(THREE.OrthographicCamera
)和透视相机(THREE.PerspectiveCamera
),以满足不同的渲染需求。
渲染器是 Three.js 中的另一个核心概念,它负责将 3D 世界中的对象渲染到屏幕上。Three.js 提供了多种渲染器类型,如 WebGL 渲染器(THREE.WebGLRenderer
)和 Canvas 渲染器(THREE.CanvasRenderer
),以满足不同的渲染需求。
以下是一个简单的 Three.js 示例,展示了如何创建一个场景、相机和渲染器:
// 创建场景
var scene = new THREE.Scene();
// 创建相机
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 创建渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 渲染场景
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
在这个示例中,我们创建了一个场景、一个透视相机和一个 WebGL 渲染器。然后,我们将渲染器的 DOM 元素添加到页面中,并使用 requestAnimationFrame 函数来实现动画效果。
几何体是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的形状。Three.js 提供了多种几何体类型,如立方体(THREE.BoxGeometry
)、球体(THREE.SphereGeometry
)、圆锥体(THREE.ConeGeometry
)等。
材质是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的表面特性,如颜色、纹理、光照等。Three.js 提供了多种材质类型,如基本材质(THREE.MeshBasicMaterial
)、兰伯特材质(THREE.MeshLambertMaterial
)、冯氏材质(THREE.MeshPhongMaterial
)等。
光源是 Three.js 中的一个核心概念,它表示 3D 世界中的光源,可以对物体的表面产生影响。Three.js 提供了多种光源类型,如平行光(THREE.DirectionalLight
)、点光源(THREE.PointLight
)、聚光灯(THREE.SpotLight
)等。
网格是 Three.js 中的一个核心概念,它表示 3D 世界中的物体,由几何体和材质组成。Three.js 提供了 THREE.Mesh
类来表示网格。
纹理是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的表面贴图。Three.js 提供了多种纹理类型,如图片纹理(THREE.Texture
)、立方体纹理(THREE.CubeTexture
)、视频纹理(THREE.VideoTexture
)等。
动画是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的运动和变化。Three.js 提供了多种动画类型,如骨骼动画(THREE.Skeleton
)、变换动画(THREE.TransformControls
)等。
碰撞检测是 Three.js 中的一个核心概念,它表示 3D 世界中的物体之间的碰撞和接触。Three.js 提供了多种碰撞检测算法,如轴对齐边界框(AABB)、球面边界框(Sphere)等。
以下是一个简单的 Three.js 示例,展示了如何创建一个几何体、材质和网格,并将其添加到场景中:
// 创建几何体
var geometry = new THREE.BoxGeometry(1, 1, 1);
// 创建材质
var material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
// 创建网格
var mesh = new THREE.Mesh(geometry, material);
// 将网格添加到场景中
scene.add(mesh);
在这个示例中,我们创建了一个立方体几何体、一个基本材质和一个网格,并将其添加到场景中。然后,我们使用 requestAnimationFrame
函数来实现动画效果。
以上提到的所有关键词和概念,在后续学习过程中,逐个细致学习掌握。加油!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- 引入初始化样式 -->
<link rel="stylesheet" href="./reset.css" />
</head>
<body>
<!-- 使用模块化方式引入入口文件 -->
<script src="./goboy.js" type="module"></script>
<div id="stage"></div>
<canvas id="text" width="700" height="200"></canvas>
<input id="input" type="text" value="GoBoy IS ME"/>
</body>
</html>
// 导入 THREE 库
import * as THREE from 'three';
// 定义变量
var height,
width,
container,
scene,
camera,
renderer,
particles = [],
mouseVector = new THREE.Vector3(0, 0, 0),
mousePos = new THREE.Vector3(0, 0, 0),
cameraLookAt = new THREE.Vector3(0, 0, 0),
cameraTarget = new THREE.Vector3(0, 0, 800), // 摄像机的目标位置
textCanvas,
textCtx,
textPixels = [],
input;
// 粒子的颜色数组
var colors = ['#F7A541', '#F45D4C', '#FA2E59', '#4783c3', '#9c6cb7'];
// 初始化舞台,设置宽度和高度,并添加事件监听器
function initStage() {
width = window.innerWidth;
height = window.innerHeight;
container = document.getElementById('stage');
window.addEventListener('resize', resize); // 监听窗口大小变化事件
container.addEventListener('mousemove', mousemove); // 监听鼠标移动事件
}
// 初始化场景
function initScene() {
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({
alpha: true, // 设置透明度
antialias: true // 开启抗锯齿
});
renderer.setPixelRatio(window.devicePixelRatio); // 设置像素比
renderer.setSize(width, height); // 设置渲染器大小
container.appendChild(renderer.domElement); // 将渲染器添加到 DOM 中
}
// 随机生成粒子的初始位置
function randomPos(vector) {
var radius = width * 3;
var centerX = 0;
var centerY = 0;
var r = width + radius * Math.random();
var angle = Math.random() * Math.PI * 2;
vector.x = centerX + r * Math.cos(angle);
vector.y = centerY + r * Math.sin(angle);
}
// 初始化摄像机
function initCamera() {
var fieldOfView = 75;
var aspectRatio = width / height;
var nearPlane = 1;
var farPlane = 3000;
camera = new THREE.PerspectiveCamera(
fieldOfView,
aspectRatio,
nearPlane,
farPlane
);
camera.position.z = 800; // 设置摄像机位置
}
// 创建光源
function createLights() {
// 创建方向光源
var shadowLight = new THREE.DirectionalLight(0xffffff, 2);
shadowLight.position.set(20, 0, 10);
shadowLight.castShadow = true; // 投射阴影
shadowLight.shadowDarkness = 0.01; // 阴影深度
scene.add(shadowLight);
// 创建方向光源
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.set(-20, 0, 20);
scene.add(light);
// 创建方向光源
var backLight = new THREE.DirectionalLight(0xffffff, 0.8);
backLight.position.set(0, 0, -20);
scene.add(backLight);
}
// 定义粒子构造函数
function Particle() {
this.vx = Math.random() * 0.05; // x 方向速度
this.vy = Math.random() * 0.05; // y 方向速度
}
// 粒子的初始化方法
Particle.prototype.init = function(i) {
var particle = new THREE.Object3D();
var geometryCore = new THREE.BoxGeometry(20, 20, 20); // 创建几何体
var materialCore = new THREE.MeshLambertMaterial({
color: colors[i % colors.length], // 随机选择颜色
shading: THREE.FlatShading // 设置着色方式
});
var box = new THREE.Mesh(geometryCore, materialCore);
box.geometry.__dirtyVertices = true;
box.geometry.dynamic = true;
particle.targetPosition = new THREE.Vector3(
(textPixels[i].x - width / 2) * 4,
textPixels[i].y * 5,
-10 * Math.random() + 20
);
particle.position.set(width * 0.5, height * 0.5, -10 * Math.random() + 20);
randomPos(particle.position);
// 修改顶点的位置
var positionAttribute = box.geometry.attributes.position;
if (positionAttribute) {
var positions = positionAttribute.array;
for (var i = 0; i < positions.length; i += 3) {
positions[i] += -10 + Math.random() * 20;
positions[i + 1] += -10 + Math.random() * 20;
positions[i + 2] += -10 + Math.random() * 20;
}
positionAttribute.needsUpdate = true;
} else {
console.error("Geometry does not have position attribute.");
}
particle.add(box);
this.particle = particle;
};
// 更新粒子的旋转角度
Particle.prototype.updateRotation = function() {
this.particle.rotation.x += this.vx;
this.particle.rotation.y += this.vy;
};
// 更新粒子的位置
Particle.prototype.updatePosition = function() {
this.particle.position.lerp(this.particle.targetPosition, 0.02);
};
// 渲染场景
function render() {
renderer.render(scene, camera);
}
// 更新粒子状态
function updateParticles() {
for (var i = 0, l = particles.length; i < l; i++) {
particles[i].updateRotation();
particles[i].updatePosition();
}
}
// 设置粒子的位置
function setParticles() {
for (var i = 0; i < textPixels.length; i++) {
if (particles[i]) {
particles[i].particle.targetPosition.x =
(textPixels[i].x - width / 2) * 4;
particles[i].particle.targetPosition.y = textPixels[i].y * 5;
particles[i].particle.targetPosition.z = -10 * Math.random() + 20;
} else {
var p = new Particle();
p.init(i);
scene.add(p.particle);
particles[i] = p;
}
}
for (var i = textPixels.length; i < particles.length; i++) {
randomPos(particles[i].particle.targetPosition);
}
}
// 初始化画布
function initCanvas() {
textCanvas = document.getElementById('text');
textCanvas.style.width = width + 'px';
textCanvas.style.height = 200 + 'px';
textCanvas.width = width;
textCanvas.height = 200;
textCtx = textCanvas.getContext('2d');
textCtx.font = '700 100px Arial';
textCtx.fillStyle = '#555';
}
// 初始化输入框
function initInput() {
input = document.getElementById('input');
input.addEventListener('keyup', updateText);
input.value = 'GoBoy IS ME';
}
// 更新文本内容
function updateText() {
var fontSize = width / (input.value.length * 1.3);
if (fontSize > 120) fontSize = 120;
textCtx.font = '700 ' + fontSize + 'px Arial';
textCtx.clearRect(0, 0, width, 200);
textCtx.textAlign = 'center';
textCtx.textBaseline = 'middle';
textCtx.fillText(input.value.toUpperCase(), width / 2, 50);
var pix = textCtx.getImageData(0, 0, width, 200).data;
textPixels = [];
for (var i = pix.length; i >= 0; i -= 4) {
if (pix[i] != 0) {
var x = (i / 4) % width;
var y = Math.floor(Math.floor(i / width) / 4);
if (x && x % 6 == 0 && y && y % 6 == 0)
textPixels.push({
x: x,
y: 200 - y + -120
});
}
}
setParticles();
}
// 动画循环
function animate() {
requestAnimationFrame(animate);
updateParticles();
camera.position.lerp(cameraTarget, 0.2);
camera.lookAt(cameraLookAt);
render();
}
// 窗口大小变化时的响应函数
function resize() {
width = window.innerWidth;
height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
textCanvas.style.width = width + 'px';
textCanvas.style.height = 200 + 'px';
textCanvas.width = width;
textCanvas.height = 200;
updateText();
}
// 鼠标移动时的响应函数
function mousemove(e) {
var x = e.pageX - width / 2;
var y = e.pageY - height / 2;
cameraTarget.x = x * -1;
cameraTarget.y = y;
}
// 初始化舞台
initStage();
// 初始化场景
initScene();
// 初始化画布
initCanvas();
// 初始化摄像机
initCamera();
// 创建光源
createLights();
// 初始化输入框
initInput();
// 开始动画
animate();
// 稍微延迟更新文本内容,以确保初始状态正确显示
setTimeout(function() {
updateText();
}, 40);
body {
overflow: hidden;
background: #A1DBB2;
}
div, canvas {
position: absolute;
}
#text {
z-index: 200;
display: none;
}
input {
z-index: 400;
position: absolute;
text-transform: uppercase;
width: 90%;
bottom: 20px;
background: none;
outline: none;
border: none;
font-size: 30px;
color: #222;
font-weight: bold;
text-align: center;
border-bottom: 1px solid #333;
left: 5%;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。