Three.js 扩散圈教程 扩散圈 ·Ripple Circle· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么Sprite始终面向相机的 billboard 用法用scale opacity模拟雷达/定位扩散圈depthWrite: false避免透明精灵深度冲突效果说明一张圆形 PNG 贴图作为 Sprite周期性放大并淡出形成从中心向外扩散的波纹常见于地图定位、雷达扫描 UI。核心概念Sprite vs Mesh| | Sprite | Mesh Plane | |---|--------|------------| | 朝向 | 永远面向相机 | 固定朝向 | | 用途 | 光点、标注、扩散圈 | 地面贴花 |const material new THREE.SpriteMaterial({map: texture, transparent: true, depthWrite: false, // 透明叠加时不写深度 }); const sprite new THREE.Sprite(material);脉冲动画逻辑let circle_n 0;function animate() { circle_n circle_n 10 ? 0 : circle_n 0.2; const scale 0.1 * circle_n 0.1; sprite.scale.set(scale, scale, scale); sprite.material.opacity Math.max(1 - circle_n * 0.05, 0.2); }circle_n0→10 循环scale 从小到大opacity 从 1 到 0.2然后重置。代码要点import * as THREE from three;import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js;// 初始化场景 const scene new THREE.Scene(); const box document.getElementById(box);// 初始化透视相机添加lookAt确保朝向场景中心 const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000); camera.position.set(5, 5, 5); camera.lookAt(0, 0, 0); // 确保相机朝向场景中心// 初始化渲染器 const renderer new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true }); renderer.setSize(box.clientWidth, box.clientHeight); renderer.setClearColor(0x808080, 1); // 设置背景颜色与原代码一致 box.appendChild(renderer.domElement);// 调试辅助添加坐标轴辅助器 const axesHelper new THREE.AxesHelper(5); scene.add(axesHelper);// 初始化纹理加载添加错误处理 const textureLoader new THREE.TextureLoader(); let texture textureLoader.load( HOST files/images/circle.png, undefined, undefined, (err) { console.error(纹理加载失败:, err); // 加载失败时使用默认材质 texture new THREE.TextureLoader().load(https://threejs.org/examples/textures/sprites/disc.png); } );// 创建精灵材质 let material new THREE.SpriteMaterial({ map: texture, color: 0xff0000, transparent: true, opacity: 1, depthWrite: false });// 创建精灵添加初始位置调试 const sprite new THREE.Sprite(material); sprite.position.set(0, 0, 0); // 初始位置改为场景中心 sprite.scale.set(1, 1, 1); // 初始缩放改为1 scene.add(sprite);// 添加环境光增强光照 const ambientLight new THREE.AmbientLight(0xffffff, 2); // 增强环境光强度 scene.add(ambientLight);// 添加轨道控制器方便调试观察 const controls new OrbitControls(camera, renderer.domElement); controls.enableDamping true; controls.dampingFactor 0.05;// 动画参数 let circle_n 0; function animate() { requestAnimationFrame(animate);// 更新控制器 controls.update();// 精灵动画逻辑 circle_n circle_n 10 ? 0 : circle_n 0.2; const scale 0.1 * circle_n 0.1; sprite.scale.set(scale, scale, scale);// 保持最小透明度防止完全消失 sprite.material.opacity Math.max(1 - circle_n * 0.05, 0.2);renderer.render(scene, camera); }// 窗口大小调整处理 window.addEventListener(resize, () { camera.aspect window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); });// 启动动画 animate();// 调试信息输出 setTimeout(() { console.log(场景内容:, scene.children); console.log(相机位置:, camera.position); console.log(精灵位置:, sprite.position); }, 1000);完整源码GitHub小结本文提供扩散圈完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库