前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Three.JS的第一个三弟(3D)案例

Three.JS的第一个三弟(3D)案例

原创
作者头像
GoBoy
发布2024-04-23 16:13:13
1440
发布2024-04-23 16:13:13
举报
文章被收录于专栏:GoboyGoboy

Three.js简介概述

three.js是世界上最流行的用于在Web上显示3D内容的JavaScript框架。

Three.js概述

Three.js 是基于 WebGL 技术,用于浏览器中开发 3D 交互场景的 JS 引擎。

默认 WebGL 只支持简单的 点、线、三角,Three.js 就是在此 WebGL 基础之上,封装出强大且使用起来简单的 JS 3D 类库。

目前主流现代浏览器都已支持 WebGL,也意味着支持 Three.js。

Three.js优缺点

🟢 优点

  1. 基于WebGL技术:Three.js建立在WebGL之上,利用了浏览器的硬件加速能力,能够高效地进行3D渲染,实现流畅的交互体验。
  2. 易用性:相比直接使用原始的WebGL,Three.js提供了更高级的抽象和封装,使得开发者能够更轻松地创建复杂的3D场景,降低了学习和使用的门槛。
  3. 跨平台性:Three.js基于Web技术,能够在主流现代浏览器上运行,包括桌面端和移动端,实现了跨平台的兼容性。

🔴 缺点

  1. 不擅长物理碰撞:虽然Three.js能够实现复杂的3D场景渲染,但其并不擅长处理物理碰撞,这使得它在开发3D游戏等需要物理交互的应用时显得力不从心。
  2. 学习曲线:尽管相比原始的WebGL,Three.js提供了更高级的抽象和封装,但仍然需要一定的学习成本,特别是对于新手来说,需要掌握一定的3D图形学知识和API使用方法。
  3. 性能依赖于硬件:由于Three.js是基于WebGL技术的,其性能受限于用户设备的硬件性能,较低配置的设备可能无法实现流畅的渲染效果。
  4. 不适合大规模应用:虽然Three.js能够满足一般的3D场景需求,但在需要处理大规模数据或者复杂计算的情况下,可能会遇到性能瓶颈。

官网示例

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技术名词

3大核心关键模块

🐔 场景(Scene)

场景是 Three.js 中的一个核心概念,它是所有 3D 对象的容器。场景可以包含几何体、光源、相机等,它们共同构成了一个完整的 3D 世界。在 Three.js 中,场景是通过 THREE.Scene 类来表示的。

🐔 相机(Camera)

相机是 Three.js 中的另一个核心概念,它负责捕捉 3D 世界中的对象,并将它们渲染到屏幕上。Three.js 提供了多种相机类型,如正交相机(THREE.OrthographicCamera)和透视相机(THREE.PerspectiveCamera),以满足不同的渲染需求。

🐔 渲染器(Renderer)

渲染器是 Three.js 中的另一个核心概念,它负责将 3D 世界中的对象渲染到屏幕上。Three.js 提供了多种渲染器类型,如 WebGL 渲染器(THREE.WebGLRenderer)和 Canvas 渲染器(THREE.CanvasRenderer),以满足不同的渲染需求。

以下是一个简单的 Three.js 示例,展示了如何创建一个场景、相机和渲染器:

代码语言:javascript
复制
// 创建场景
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 函数来实现动画效果。

其他技术关键词

💯 几何体(Geometry)

几何体是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的形状。Three.js 提供了多种几何体类型,如立方体(THREE.BoxGeometry)、球体(THREE.SphereGeometry)、圆锥体(THREE.ConeGeometry)等。

💯 材质(Material)

材质是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的表面特性,如颜色、纹理、光照等。Three.js 提供了多种材质类型,如基本材质(THREE.MeshBasicMaterial)、兰伯特材质(THREE.MeshLambertMaterial)、冯氏材质(THREE.MeshPhongMaterial)等。

💯 光源(Light)

光源是 Three.js 中的一个核心概念,它表示 3D 世界中的光源,可以对物体的表面产生影响。Three.js 提供了多种光源类型,如平行光(THREE.DirectionalLight)、点光源(THREE.PointLight)、聚光灯(THREE.SpotLight)等。

💯 网格(Mesh)

网格是 Three.js 中的一个核心概念,它表示 3D 世界中的物体,由几何体和材质组成。Three.js 提供了 THREE.Mesh 类来表示网格。

💯 纹理(Texture)

纹理是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的表面贴图。Three.js 提供了多种纹理类型,如图片纹理(THREE.Texture)、立方体纹理(THREE.CubeTexture)、视频纹理(THREE.VideoTexture)等。

💯 动画(Animation)

动画是 Three.js 中的一个核心概念,它表示 3D 世界中的物体的运动和变化。Three.js 提供了多种动画类型,如骨骼动画(THREE.Skeleton)、变换动画(THREE.TransformControls)等。

💯 碰撞检测(Collision Detection)

碰撞检测是 Three.js 中的一个核心概念,它表示 3D 世界中的物体之间的碰撞和接触。Three.js 提供了多种碰撞检测算法,如轴对齐边界框(AABB)、球面边界框(Sphere)等。

以下是一个简单的 Three.js 示例,展示了如何创建一个几何体、材质和网格,并将其添加到场景中:

代码语言:javascript
复制
// 创建几何体
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 函数来实现动画效果。

以上提到的所有关键词和概念,在后续学习过程中,逐个细致学习掌握。加油!!!

表演个小示例

👽 创建 index.html

代码语言:html
复制
<!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>

👽 创建 goboy.js

代码语言:javascript
复制
// 导入 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);

👽 创建 goboy.css

代码语言:css
复制
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%;
  }

👽 展示效果

Three.js相关资料官网

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Three.js简介概述
    • three.js是世界上最流行的用于在Web上显示3D内容的JavaScript框架。
    • Three.js概述
    • Three.js优缺点
      • 🟢 优点
        • 🔴 缺点
        • 官网示例
        • Three.js应用场景
        • Three.js技术名词
          • 3大核心关键模块
            • 🐔 场景(Scene):
            • 🐔 相机(Camera):
            • 🐔 渲染器(Renderer):
          • 其他技术关键词
            • 💯 几何体(Geometry):
            • 💯 材质(Material):
            • 💯 光源(Light):
            • 💯 网格(Mesh):
            • 💯 纹理(Texture):
            • 💯 动画(Animation):
            • 💯 碰撞检测(Collision Detection):
        • 表演个小示例
          • 👽 创建 index.html
            • 👽 创建 goboy.js
              • 👽 创建 goboy.css
                • 👽 展示效果
                • Three.js相关资料官网
                相关产品与服务
                容器服务
                腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档