使用Three.js实现字符串字符依次缩放动画失败,求解决
字符依次缩放动画的Three.js代码问题排查与修复
你的代码无法正常运行的核心问题在于字符几何体复用错误,以及位置计算的不合理,以下是具体问题分析和修复方案:
问题分析
- 几何体复用错误:你创建了一个包含完整文本的
TextGeometry,然后用它生成所有字符的网格,导致每个网格渲染的都是完整的"Hello, World!",而非单个字符,自然看不到预期的逐个缩放效果。 - 位置计算不合理:固定的80像素间距没有考虑不同字符的实际宽度,会导致字符重叠或间距不均,影响视觉效果。
修复后的代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Zoom In/Out Text Animation</title> <style> body { margin: 0; padding: 0; background-color: #000; } canvas { display: block; } </style> </head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script> // 初始化场景、相机、渲染器 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 文本内容与字体加载 const text = "Hello, World!"; const fontLoader = new THREE.FontLoader(); fontLoader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', function(font) { const material = new THREE.MeshBasicMaterial({color: 0xffffff}); const meshes = []; let totalWidth = 0; const charGeometries = []; // 先创建所有字符的几何体,计算总宽度 for (let i = 0; i < text.length; i++) { const charGeometry = new THREE.TextGeometry(text[i], { font: font, size: 50, height: 5, curveSegments: 12, bevelEnabled: true, bevelThickness: 2, bevelSize: 1, bevelSegments: 5 }); charGeometry.computeBoundingBox(); charGeometries.push(charGeometry); totalWidth += charGeometry.boundingBox.max.x - charGeometry.boundingBox.min.x; // 字符间添加间距 totalWidth += 20; } // 计算起始位置,让文本居中 let currentX = -totalWidth / 2; // 创建每个字符的网格并设置位置 for (let i = 0; i < text.length; i++) { const geometry = charGeometries[i]; const mesh = new THREE.Mesh(geometry, material); // 让字符基于自身中心定位 const charWidth = geometry.boundingBox.max.x - geometry.boundingBox.min.x; mesh.position.x = currentX + charWidth / 2; currentX += charWidth + 20; meshes.push(mesh); scene.add(mesh); } // 动画函数:逐个字符缩放 const animate = function () { requestAnimationFrame(animate); const time = Date.now() * 0.002; meshes.forEach((mesh, index) => { // 每个字符的动画延迟依次递增,实现依次缩放效果 const scale = Math.sin(time + index * Math.PI / 4) * 0.3 + 1.0; mesh.scale.set(scale, scale, scale); }); renderer.render(scene, camera); }; animate(); }); // 设置相机位置 camera.position.z = 300; </script> </body> </html>
关键修复点
- 为每个字符单独创建
TextGeometry,确保每个网格只渲染单个字符。 - 通过
computeBoundingBox()计算每个字符的实际宽度,动态调整位置,让文本居中且间距合理。 - 调整动画的相位偏移,让字符缩放的先后顺序更明显,增强依次动画的效果。
- 增加相机z轴距离,确保所有字符都在视野范围内。
内容的提问来源于stack exchange,提问作者Humberto José Bortolossi
相关产品推荐
相关产品推荐

