上述HTML文档是一个使用Three.js库创建的简单WebGL应用程序,主要用于展示具有不同透明度和缩放比例的圆环列。以下是代码的详细解释:
- HTML结构:
- 文档类型声明为HTML5。
<html>
标签设置了语言属性为英语(lang="en"
)。<head>
部分包含了文档的标题、字符集设置和视口设置。视口设置确保页面在移动设备上以适当的比例显示,不允许用户缩放。<style>
标签内定义了一些基本的CSS样式,主要是去除body
的默认边距,并设置canvas
元素为块级显示。
- JavaScript部分(使用ES6模块):
- 通过
import
语句导入了Three.js库及其相关模块,包括OrbitControls
用于相机交互。 - 初始化Three.js的核心组件:
- 创建一个场景(
Scene
)。 - 创建一个透视相机(
PerspectiveCamera
),其视场角为75度,宽高比根据窗口大小动态计算,近剪裁面为0.1,远剪裁面为1000。 - 创建一个WebGL渲染器(
WebGLRenderer
),并设置其大小与窗口大小相匹配,然后将渲染器的DOM元素添加到body
中。
- 创建一个场景(
- 创建一个包含四个圆环的数组
meshes
:- 每个圆环使用
RingGeometry
定义,具有不同的透明度和缩放比例。 - 圆环的材质使用
MeshBasicMaterial
,并设置颜色、透明度、是否透明以及双面渲染。 - 将每个创建好的圆环网格对象(
Mesh
)添加到meshes
数组中。
- 每个圆环使用
- 遍历
meshes
数组,并将每个圆环添加到场景中。 - 添加光照:
- 一个环境光(
AmbientLight
)用于基础照明。 - 一个聚光灯(
SpotLight
)用于强调照明效果,位置设置为(10, 10, 10)。
- 一个环境光(
- 设置相机位置,
z
轴为50,以便观察场景。 - 添加
OrbitControls
以允许用户通过鼠标和键盘交互地移动相机。 - 定义一个
render
函数,用于动态改变圆环的透明度和缩放比例。这里有一个逻辑判断,如果透明度降至0以下,则重置为1,并缩放比例重置为(1, 1, 1);否则,逐渐减小透明度和增大缩放比例。 - 创建一个动画循环
animate
,使用requestAnimationFrame
确保动画平滑,每次循环调用render
函数、更新OrbitControls
并渲染场景。 - 添加一个事件监听器,用于处理窗口大小变化时更新相机的宽高比和渲染器的大小。
- 最后,启动动画循环。
- 通过
- 功能概述:
- 页面加载时,用户将看到一个包含四个圆环的场景,每个圆环具有不同的透明度和动态变化的缩放比例。
- 用户可以通过鼠标和键盘使用
OrbitControls
来旋转、平移和缩放相机,以不同角度观察场景。 - 随着动画的进行,圆环的透明度和缩放比例将不断变化,创造一种动态效果。
总之,这段代码展示了一个基本的Three.js应用,通过动态改变对象的属性和使用简单的光照来创建一个有趣的视觉效果。
<!DOCTYPE html>
<html lang="en"><head><title>three.js webgl - particles - columns</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"><style>body {margin: 0;}canvas {display: block;}</style>
</head><body><script type="module">import * as THREE from 'three';import { Scene, PerspectiveCamera, WebGLRenderer, AmbientLight, Color, SpotLight } from "three";import { OrbitControls } from 'three/addons/controls/OrbitControls.js';// 初始化场景、相机和渲染器 const scene = new Scene();const camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);const renderer = new WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);const meshes = [];for (let i = 0; i < 4; i++) {const geometry = new THREE.RingGeometry(0.9, 1, 64);const opacity = 1 - i / 4; // 计算透明度 const scale = (16 * i) / 4 + 1; // 计算缩放比例 const material = new THREE.MeshBasicMaterial({color: 0x3184ae,transparent: true,opacity: opacity, // 使用计算的透明度 side: THREE.DoubleSide});const mesh = new THREE.Mesh(geometry, material);mesh.scale.set(scale, scale, 1);meshes.push(mesh);}// 遍历 meshes 数组,并将每个 mesh 添加到场景中 meshes.forEach(mesh => {scene.add(mesh);});//// 添加环境光和聚光灯 const ambientLight = new AmbientLight(0xffffff, 0.5);scene.add(ambientLight);const spotLight = new SpotLight(0xffffff, 1);spotLight.position.set(10, 10, 10);scene.add(spotLight);/// 设置相机位置 camera.position.z = 50;// 添加OrbitControls以便交互 const controls = new OrbitControls(camera, renderer.domElement);const render = () => {meshes.forEach((mesh, index) => {const meterial = mesh.material;if (meterial.opacity <= 0) {meterial.opacity = 1;mesh.scale.set(1, 1, 1);} else { meterial.opacity -= 0.002; mesh.scale.set(mesh.scale.x + 0.038, mesh.scale.y + 0.038, 1); }});};// 创建动画循环 const animate = function () {requestAnimationFrame(animate);render();controls.update(); // 更新OrbitControls renderer.render(scene, camera);};// 处理窗口大小调整 window.addEventListener('resize', () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);});// 开始动画循环 animate();</script>
</body></html>