Three.js - 打开Web 3D世界的大门

文章目录

    • 前言
    • [一、Three.js 的起源与背景](#一、Three.js 的起源与背景)
    • [二、Three.js 的特点](#二、Three.js 的特点)
    • [三、Three.js 的核心组件详解](#三、Three.js 的核心组件详解)
    • 四、实际应用案例
    • 结语

前言

Three.js 是一个基于JavaScript的库,它极大地简化了使用WebGL创建3D图形的过程。通过封装复杂的WebGL API,Three.js为开发者提供了一个更加友好和高效的开发环境,使得即使是对3D编程不太熟悉的开发者也能够快速上手,并创造出令人印象深刻的交互式3D内容。


一、Three.js 的起源与背景

Three.js 是由一位西班牙的开发者 Ricardo Cabello(又名 Mr.doob)于2010年发起的项目。其初衷是为了简化WebGL(Web Graphics Library)的使用难度,因为直接使用WebGL进行3D渲染需要大量的代码编写,并且API相对复杂。Three.js通过封装WebGL的功能,提供了一个更加友好、易于使用的接口,使得更多的开发者可以快速上手并创造出令人惊艳的3D内容。

二、Three.js 的特点

  • 易用性:Three.js 提供了丰富的文档和支持,拥有庞大的社区,对于初学者来说是一个很好的入门选择。
  • 跨平台兼容性:由于它是基于WebGL构建的,因此可以在任何支持HTML5和WebGL的浏览器上运行,无需安装额外的插件。
  • 广泛的适用性:无论是游戏开发、虚拟现实应用还是数据可视化,Three.js都能提供强有力的支持。
  • 性能优化:随着版本迭代,Three.js不断改进性能,确保即使是在处理复杂场景时也能保持流畅。

三、Three.js 的核心组件详解

场景(Scene)

场景是所有3D对象、光源和其他元素的容器。在Three.js中,我们首先需要创建一个场景对象,然后将其他组件添加到这个场景中。

javascript 复制代码
const scene = new THREE.Scene();

相机(Camera)

相机决定了用户从哪个视角观看场景。Three.js提供了多种类型的相机,如透视相机(PerspectiveCamera),它模仿人眼的视觉效果,适合大多数应用场景;还有正交相机(OrthographicCamera),它用于创建技术图纸或UI元素等不需要透视效果的内容。

javascript 复制代码
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

渲染器(Renderer)

渲染器负责将场景中的内容绘制到HTML页面上的canvas元素中。Three.js支持多种渲染器,但最常用的是WebGLRenderer,因为它提供了最好的性能和兼容性。

javascript 复制代码
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

物体(Object)

物体是由几何形状(Geometry)和材质(Material)组成的3D模型。Three.js内置了许多常见的几何形状,比如球体、立方体、圆柱体等,并且可以通过自定义几何体来实现更复杂的设计。

javascript 复制代码
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

动画与交互

Three.js不仅限于静态图像,还支持动画和用户交互。你可以使用requestAnimationFrame循环更新场景,或者监听鼠标事件来响应用户的操作。

javascript 复制代码
function animate() {
    requestAnimationFrame(animate);

    // 更新物体的位置或旋转等属性
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera);
}
animate();

四、实际应用案例

案例1:旋转的立方体

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Simple FPS Game</title>
  <style>
    body {
      margin: 0;
    }

    canvas {
      display: block;
    }
  </style>
</head>

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

  <script>
    // 创建场景
    var scene = new THREE.Scene();

    // 创建相机
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 5;

    // 创建渲染器
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 创建一个立方体几何体
    var geometry = new THREE.BoxGeometry();
    // 创建一个材质
    var material = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
    // 创建一个网格(几何体 + 材质)
    var cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 渲染函数
    function animate() {
      requestAnimationFrame(animate);

      // 旋转立方体
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;

      renderer.render(scene, camera);
    }

    // 开始动画循环
    animate();

    // 处理窗口大小调整
    window.addEventListener('resize', function () {
      var width = window.innerWidth;
      var height = window.innerHeight;
      renderer.setSize(width, height);
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
    });
  </script>
</body>

</html>

案例2:轨道运动动画

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Simple FPS Game</title>
  <style>
    body {
      margin: 0;
    }

    canvas {
      display: block;
    }
  </style>
</head>

<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

  <script>
    // 初始化场景、相机和渲染器
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    var renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 创建球体并设置初始位置
    function createOrbitingSphere(radius, distance, speed) {
      var geometry = new THREE.SphereGeometry(radius, 32, 32);
      var material = new THREE.MeshBasicMaterial({ color: Math.random() * 0xffffff });
      var sphere = new THREE.Mesh(geometry, material);
      sphere.position.x = distance;
      sphere.distance = distance;
      sphere.angle = 0;
      sphere.speed = speed;
      scene.add(sphere);
      return sphere;
    }

    var spheres = [];
    for (var i = 0; i < 10; i++) {
      spheres.push(createOrbitingSphere(0.5 + Math.random(), 5 + i * 2, 0.005 + Math.random() * 0.01));
    }

    camera.position.z = 20;

    function animate() {
      requestAnimationFrame(animate);

      spheres.forEach(function (sphere) {
        sphere.angle += sphere.speed;
        sphere.position.x = Math.cos(sphere.angle) * sphere.distance;
        sphere.position.y = Math.sin(sphere.angle) * sphere.distance;
      });

      renderer.render(scene, camera);
    }

    animate();

    // 窗口调整事件处理
    window.addEventListener('resize', function () {
      var width = window.innerWidth;
      var height = window.innerHeight;
      renderer.setSize(width, height);
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
    });
  </script>
</body>

</html>

案例3:随机生成的粒子系统

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Simple FPS Game</title>
  <style>
    body {
      margin: 0;
    }

    canvas {
      display: block;
    }
  </style>
</head>

<body>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

  <script>
    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    var renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    camera.position.z = 50;

    var particlesCount = 5000;
    var particlesGeometry = new THREE.BufferGeometry();
    var particlesPositions = new Float32Array(particlesCount * 3);

    for (var i = 0; i < particlesCount * 3; i++) {
      particlesPositions[i] = (Math.random() - 0.5) * 100;
    }

    particlesGeometry.setAttribute('position', new THREE.BufferAttribute(particlesPositions, 3));

    var particlesMaterial = new THREE.PointsMaterial({ color: 0x00ff00 });
    var particles = new THREE.Points(particlesGeometry, particlesMaterial);
    scene.add(particles);

    function animateParticles() {
      var positions = particles.geometry.attributes.position.array;
      for (var i = 0; i < positions.length; i += 3) {
        positions[i + 1] -= 0.1;

        if (positions[i + 1] < -50) {
          positions[i + 1] = 50;
        }
      }
      particles.geometry.attributes.position.needsUpdate = true;
    }

    function animate() {
      requestAnimationFrame(animate);
      animateParticles();
      renderer.render(scene, camera);
    }

    animate();

    // 窗口调整事件处理
    window.addEventListener('resize', function () {
      var width = window.innerWidth;
      var height = window.innerHeight;
      renderer.setSize(width, height);
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
    });
  </script>
</body>

</html>

结语

Three.js作为Web 3D开发的强大工具,正在不断推动着网络技术的发展边界。无论是创建沉浸式的用户体验、教育工具,还是进行复杂的数据可视化,Three.js都展现出了其独特的价值。随着社区的不断壮大和技术的进步,Three.js的应用前景无疑将更加广阔。

相关推荐
yume_sibai1 小时前
06-Rust Web 开发实战(Axum 框架 + 数据库 + JWT 认证 + 中间件 + 部署)
前端·数据库·rust
计算机魔术师2 小时前
特朗普上台打给黄仁勋:AI末日论是骗局,我们绝不让它发生
前端
troy1282 小时前
Python 基础语法(八):Web 后端开发、数据分析与可视化、网络爬虫、人工智能 / 大模型应用
前端·python·数据分析
计算机魔术师3 小时前
CEO说要慢下来,黑客说别做梦了——同一篇论文,两种命运
前端
微财经观圈3 小时前
AI 3D生成工具重拓扑后怎样检查UV、法线和材质是否正常?
人工智能·3d·重拓扑
kyriewen3 小时前
我花3天抓了一个幽灵bug,凶手藏在第4层
前端·javascript·程序员
IT_陈寒4 小时前
Java里用Stream.parallel()翻车实录,这性能还不如单线程
前端·人工智能·后端
Zldaisy3d4 小时前
一种具备优异带外抑制特性的增材制造滤波超表面
3d
wangchunyu1144 小时前
JavaScript 零基础入门教程
前端
hanchenxing5 小时前
前端异步任务三方案:Celery vs Redis Stream vs BullMQ 实战对比消息队列
前端·数据库·redis·异步任务·方案对比