如何用Three.js React制作长尾词的3D文字悬浮动画效果?

2026-04-03 06:271阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计4549个文字,预计阅读时间需要19分钟。

如何用Three.js React制作长尾词的3D文字悬浮动画效果?

目录+背景+效果+实现+资源引入+DOM结构+设置状态+网格背景+场景初始化+材质创建+文字模型创建+几何体模型创建+鼠标事件监听+背景色切换+后期渲染+动画+缩放适配+双击全屏+总结+背景

目录
  • 背景
  • 效果
  • 实现
    • 资源引入
    • DOM结构
    • 设置状态
    • 网格背景
    • 场景初始化
    • 创建材质
    • 创建文字模型
    • 创建几何体模型
    • 鼠标事件监听
    • 背景色切换
    • 后期渲染
    • 动画
    • 缩放适配
    • 双击全屏
  • 总结

    背景

    Three.js Journey课程示例中,提供了一个使用Three.js内置方法实现的3D文字悬浮效果的例子,本文使用React + Three.js技术栈,参照示例实现类似的效果。本文中涉及到的知识点主要包括:CSS网格背景、MeshNormalMaterial法向材质、FontLoader字体加载器、TextGeometry文本缓冲几何体、TorusBufferGeometry圆环缓冲几何体、ConeBufferGeometry圆锥缓冲几何体、OctahedronBufferGeometry八面缓冲几何体、Three.js后期渲染、GlitchPass通道、Element.requestFullscreenDocument.exitFullscreen等。

    效果

    实现效果如banner图所示,页面主体由位于中心的文字网格模型以及四周的圆环面、圆锥以及八面体构成。随着鼠标在页面上移动或点击,模型也随之移动。页面右上角提供了2个按钮,可以切换页面背景色和切换故障风格后期特效。双击屏幕可以进入或退出全屏。

    在线预览:3d-dragonir.vercel.app/#/floating

    或dragonir.github.io/3d/#/floating

    已适配:

    • PC端
    • 移动端

    实现

    资源引入

    首先引入开发所需要的模块资源,其中FontLoader用于加载字体文件,TextGeometry用于创建3D字体网格,EffectComposerRenderPassGlitchPass用于后期特效渲染。

    import * as THREE from "three"; import { FontLoader } from "three/examples/jsm/loaders/FontLoader"; import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'; import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'; import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js';

    DOM结构

    页面DOM结构非常简单,容器#canvas用于场景渲染,.color_pick用于切换页面背景颜色,.pass_button用于切换故障风格后期渲染。

    <div className='floating_page' style={{ backgroundColor: this.state.backgroundColor }}> <div id="canvas"></div> <input className='color_pick' type="color" onChange={this.handleInputChange} value={this.state.backgroundColor} /> <button className='pass_button' onClick={this.handleRenderChange}>特效<span className='highlight'>{this.state.renderGlithPass ? '开' : '关'}</span></button> </div>

    设置状态

    backgroundColor表示当前页面背景色,renderGlithPass表示是否开启后期状态。自测发现在iOS Safari浏览器中,故障风格后期渲染会导致模型产生穿模问题,因此使用该参数控制手机端默认关闭后期效果、pc端默认开启。

    state = { backgroundColor: '#164CCA', renderGlithPass: !(window.navigator.userAgent.toLowerCase().indexOf('mobile') > 0) }

    网格背景

    使用纯CSS属性linear-gradient实现网格背景来美化页面。

    background-image: linear-gradient(rgba(3, 192, 60, .3) 1px, transparent 1px), linear-gradient(90deg, rgba(3, 192, 60, .3) 1px, transparent 1px); background-size: 1em 1em;

    场景初始化

    初始化渲染容器、场景、摄像机,摄像机的位置可根据自身所需调整。render开启alpha并设置.setClearAlpha(0)可将背景色设置为透明。

    canvas = document.getElementById('canvas'); renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setPixelRatio(Math.min(2, window.devicePixelRatio)); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearAlpha(0); canvas.appendChild(renderer.domElement); scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, .1, 10000); camera.position.set(-2 * 10000, 0, 780);

    创建材质

    本文中所有网格模型都将使用同一种材质MeshNormalMaterial,应用它的特性,可以使网格模型产生彩色渐变。全局创建一次,后续开发不需要重复创建,有利于页面性能提升。

    const material = new THREE.MeshNormalMaterial();

    MeshNormalMaterial 法向材质

    是一种把法向量映射到RGB颜色的材质,可以通过观察模型表面渐变颜色是否连续来检测模型表面是否平整

    构造函数

    MeshNormalMaterial(parameters : Object)

    parameters:可选,用于定义材质外观的对象,具有一个或多个属性。

    特殊属性

    • .normalMap[Texture]:用于创建法线贴图纹理,RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。
    • .normalMapType[Integer]:法线贴图的类型,选项为THREE.TangentSpaceNormalMap(默认)和THREE.ObjectSpaceNormalMap
    • .normalScale[Vector2]:法线贴图对材质的影响程度。范围是0-1,默认值是Vector2设置为(1, 1)
    • .flatShading[Boolean]:定义材质是否使用平面着色进行渲染,默认值为false
    • .morphNormals[Boolean]:定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为false
    • .morphTargets[Boolean]:定义材质是否使用morphTargets,默认值为false

    创建文字模型

    使用FontLoader加载fontface字体JSON文件,并用TextGeometry创建文字几何体模型。

    const loader = new FontLoader(); loader.load('./fonts/helvetiker_regular.typeface.json', font => { textMesh.geometry = new TextGeometry('@dragonir\nfantastic\nthree.js\nart work', { font: font, size: 100, height: 40, curveSegments: 12, bevelEnabled: true, bevelThickness: 30, bevelSize: 8, bevelOffset: 1, bevelSegments: 12 }); textMesh.material = material; scene.add(textMesh); });

    FontLoader 字体加载器

    使用JSON格式中加载字体的一个类,返回Font, 返回值是表示字体的Shape类型的数组,其内部使用FileLoader来加载文件。

    构造函数

    FontLoader(manager: LoadingManager)

    • manager:加载器所使用的loadingManager,默认值为THREE.DefaultLoadingManager

    方法:

    如何用Three.js React制作长尾词的3D文字悬浮动画效果?

    .loadURL中进行加载,并将被加载的texture传递给onLoad

    • .load(url: String, onLoad: Function, onProgress: Function, onError: Function): null
    • url:文件的URL或者路径,也可以为Data URI
    • onLoad:加载完成时将调用。回调参数是将要被加载的texture
    • onProgress:将在加载过程中进行调用。参数为XMLHttpRequest实例,包含totalloaded字节。
    • onError:加载错误时被调用。

    .parseJSON格式进行解析,并返回一个Font

    • .parse (json: Object ): Font
    • json:用于解析的JSON结构。

    TextGeometry 文本几何体

    用于将文本生成单一几何体的类,它是由一串给定的文本,以及由加载的Font字体和该几何体ExtrudeGeometry父类中的设置所组成的参数构造的。

    构造函数

    TextGeometry(text: String, parameters: Object)

    text:将要显示的文本。

    parameters

    • font[Font]THREE.Font实例。
    • size[Float]:字体大小,默认值为100
    • height[Float]:挤出文本的厚度,默认值为50
    • curveSegments[Integer]:表示文本的曲线上点的数量,默认值为12
    • bevelEnabled[Boolean]:是否开启斜角,默认为false
    • bevelThickness[Float]:文本斜角的深度,默认值为20
    • bevelSize[Float]:斜角与原始文本轮廓之间的延伸距离,默认值为8
    • bevelSegments[Integer]:斜角的分段数,默认值为3

    可以使用facetype.js在线转换Three.js支持的字体。

    创建几何体模型

    使用其他3种内置几何体模型圆环、圆锥和八面体来装饰页面。装饰几何体的数量比较多,为了有效提升页面性能,需要注意以下两点:

    • 使用THREE.Group管理所有几何体。
    • 创建几何体时使用BufferAttribute, 如使用ConeBufferGeometry而不是ConeGeometry,这样可以更有效地将数据传递到GPU

    // 批量创建模型方法 generateRandomMesh = (geometry, material, count) => { for (let i = 0; i < count; i++) { let mesh = new THREE.Mesh(geometry, material); let dist = farDist / 3; let distDouble = dist * 2; // 设置随机的位置和旋转角度 mesh.position.x = Math.random() * distDouble - dist; mesh.position.y = Math.random() * distDouble - dist; mesh.position.z = Math.random() * distDouble - dist; mesh.rotation.x = Math.random() * 2 * Math.PI; mesh.rotation.y = Math.random() * 2 * Math.PI; mesh.rotation.z = Math.random() * 2 * Math.PI; // 手动控制何时重新计算3D变换以获得更好的性能 mesh.matrixAutoUpdate = false; mesh.updateMatrix(); group.add(mesh); } } // 创建100个八面体 const octahedronGeometry = new THREE.OctahedronBufferGeometry(80); generateRandomMesh(octahedronGeometry, material, 100); // 创建200个圆环面 const torusGeometry = new THREE.TorusBufferGeometry(40, 25, 16, 40); generateRandomMesh(torusGeometry, material, 200); // 创建100个圆锥 const coneGeometry = new THREE.ConeBufferGeometry(40, 80, 80); generateRandomMesh(coneGeometry, material, 100); scene.add(group);

    TorusBufferGeometry 圆环缓冲几何体

    用于生成圆环几何体的类。

    构造函数

    TorusBufferGeometry(radius: Float, tube: Float, radialSegments: Integer, tubularSegments: Integer, arc: Float)

    • radius:圆环的半径,从圆环的中心到管道横截面的中心,默认值是1
    • tube:管道的半径,默认值为0.4
    • radialSegments:圆环的分段数,默认值为8
    • tubularSegments:管道的分段数,默认值为6
    • arc:圆环的圆心角,单位是弧度,默认值为Math.PI * 2

    ConeBufferGeometry 圆锥缓冲几何体

    用于生成圆锥几何体的类。

    构造函数

    ConeBufferGeometry(radius: Float, height: Float, radialSegments: Integer, heightSegments: Integer, openEnded: Boolean, thetaStart: Float, thetaLength: Float)

    • radius:圆锥底部的半径,默认值为1
    • height:圆锥的高度,默认值为1
    • radialSegments:圆锥侧面周围的分段数,默认为8
    • heightSegments:圆锥侧面沿着其高度的分段数,默认值为1
    • openEnded:指明该圆锥的底面是开放的还是封顶的。默认值为false,即其底面默认是封顶的。
    • thetaStart:第一个分段的起始角度,默认为0
    • thetaLength:圆锥底面圆扇区的中心角,通常被称为θ。默认值是2*PI,使其成为一个完整的圆锥。

    OctahedronBufferGeometry 八面缓冲几何体

    用于创建八面体的类。

    构造函数

    OctahedronBufferGeometry(radius: Float, detail: Integer)

    • radius:八面体的半径,默认值为1
    • detail:默认值为0,将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个八面体。

    鼠标事件监听

    通过对鼠标移动坐标和模型坐标的相互转换来添加鼠标移动和触摸移动事件的监听方法。

    const mouseFX = { windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, coordinates: (coordX, coordY) => { mouseX = (coordX - mouseFX.windowHalfX) * 5; mouseY = (coordY - mouseFX.windowHalfY) * 5; }, onMouseMove: e => { mouseFX.coordinates(e.clientX, e.clientY) }, onTouchMove: e => { mouseFX.coordinates(e.changedTouches[0].clientX, e.changedTouches[0].clientY)} }; document.addEventListener('mousemove', mouseFX.onMouseMove, false); document.addEventListener('touchmove', mouseFX.onTouchMove, false);

    背景色切换

    使用一个input[type='color']标签来实现背景色切换。

    handleInputChange = e => { this.setState({ backgroundColor: e.target.value }); }

    后期渲染

    为了更具有冲击感的视觉效果,我添加了一个故障风格后期渲染特效,并使用一个按钮开关来控制开启和关闭该特效。

    composer = new EffectComposer(renderer); composer.addPass( new RenderPass(scene, camera)); glitchPass = new GlitchPass(); composer.addPass(glitchPass);

    handleRenderChange = () => { this.setState({ renderGlithPass: !this.state.renderGlithPass }); }

    后期渲染

    Three.js后期渲染处理,是通过叠加渲染通道达到预期视觉效果的过程。实现流程如下:

    • 创建效果组合器:效果组合器是各种处理通道的入口,使用EffectComposer对象创建一个效果组合器。
    • 添加通道:添加RenderPass通道 它将在指定的场景和相机的基础上渲染出一个新的场景。
    • 组合器更新:在动画循环中,调用效果组合器的render方法,通道生成效果将在场景中输出。

    GlitchPass 故障风格通道

    GlitchPass通道产生模拟故障风格效果,它只有一个可选配置参数:

    goWild该属性接收一个布尔值,指定是否持续产生电磁风暴效果。

    Three.js提供了很多后期处理的通道,可以直接使用。同时提供了ShaderPass通道,它支持使用自定义Shader,可以创建高级的自定义后期处理通道。

    动画

    requestAnimationFrame中更新场景、相机、和后期渲染通道。

    function animate() { requestAnimationFrame(animate); camera.position.x += (mouseX - camera.position.x) * 0.05; camera.position.y += (mouseY * -1 - camera.position.y) * 0.05; camera.lookAt(scene.position); // 给场景中的立方体网格和字体网格添加自转动画 const t = Date.now() * 0.001; const rx = Math.sin(t * 0.7) * 0.5; const ry = Math.sin(t * 0.3) * 0.5; const rz = Math.sin(t * 0.2) * 0.5; group.rotation.x = rx; group.rotation.y = ry; group.rotation.z = rz; textMesh.rotation.x = rx; textMesh.rotation.y = ry; textMesh.rotation.z = rx; renderer.render(scene, camera); // 更新后期渲染通道 composer.render(); }

    缩放适配

    renderercomposer大小要同时调整。

    window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); composer.setSize( window.innerWidth, window.innerHeight ); }, false);

    双击全屏

    监听页面鼠标双击dblclick事件,通过调用requestFullscreenexitFullscreen进入或退出全屏状态。

    window.addEventListener('dblclick', () => { let fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement; if (!fullscreenElement) { if (canvas.requestFullscreen) { canvas.requestFullscreen(); } else if (canvas.webkitRequestFullscreen) { canvas.webkitRequestFullscreen(); } console.log('进入全屏') } else { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } console.log('退出全屏') } })

    Element.requestFullscreen

    Element.requestFullscreen方法用于发出异步请求使元素进入全屏模式。调用此API并不能保证元素一定能够进入全屏模式。如果元素被允许进入全屏幕模式,返回的Promiseresolve,并且该元素会收到一个fullscreenchange事件,通知它已经进入全屏模式。如果全屏请求被拒绝,返回的promise会变成rejected并且该元素会收到一个fullscreenerror事件。如果该元素已经从原来的文档中分离,那么该文档将会收到这些事件。

    语法

    var Promise = Element.requestFullscreen(options);

    options:可选,一个FullscreenOptions对象提供切换到全屏模式的控制选项。

    这个方法只能在用户交互或者设备方向改变的时候调用,否则将会失败。FullscreenOptions目前唯一的选项是navigationUI,这控制了是否在元素处于全屏模式时显示导航条UI。默认值是auto,表明这将由浏览器来决定是否显示导航条。

    Document.exitFullscreen

    Document.exitFullscreen方法用于让当前文档退出全屏模式。调用这个方法会让文档回退到上一个调用Element.requestFullscreen方法进入全屏模式之前的状态。

    语法

    document.exitFullscreen();

    到此,示例页面的全部功能都完成了,可访问以下链接查看完整代码。

    完整代码:github.com/dragonir/3d/tree/master/src/containers/Floating

    总结

    本文知识点主要包含的的新知识:

    • CSS网格背景
    • MeshNormalMaterial法向材质
    • FontLoader字体加载器
    • TextGeometry文本缓冲几何体
    • TorusBufferGeometry圆环缓冲几何体
    • ConeBufferGeometry圆锥缓冲几何体
    • OctahedronBufferGeometry八面缓冲几何体
    • Three.js后期渲染
    • GlitchPass通道
    • Element.requestFullscreen
    • Document.exitFullscreen

    以上就是Three.js+React实现3D文字悬浮效果的详细内容,更多关于Three.js React文字悬浮的资料请关注自由互联其它相关文章!

    本文共计4549个文字,预计阅读时间需要19分钟。

    如何用Three.js React制作长尾词的3D文字悬浮动画效果?

    目录+背景+效果+实现+资源引入+DOM结构+设置状态+网格背景+场景初始化+材质创建+文字模型创建+几何体模型创建+鼠标事件监听+背景色切换+后期渲染+动画+缩放适配+双击全屏+总结+背景

    目录
    • 背景
    • 效果
    • 实现
      • 资源引入
      • DOM结构
      • 设置状态
      • 网格背景
      • 场景初始化
      • 创建材质
      • 创建文字模型
      • 创建几何体模型
      • 鼠标事件监听
      • 背景色切换
      • 后期渲染
      • 动画
      • 缩放适配
      • 双击全屏
    • 总结

      背景

      Three.js Journey课程示例中,提供了一个使用Three.js内置方法实现的3D文字悬浮效果的例子,本文使用React + Three.js技术栈,参照示例实现类似的效果。本文中涉及到的知识点主要包括:CSS网格背景、MeshNormalMaterial法向材质、FontLoader字体加载器、TextGeometry文本缓冲几何体、TorusBufferGeometry圆环缓冲几何体、ConeBufferGeometry圆锥缓冲几何体、OctahedronBufferGeometry八面缓冲几何体、Three.js后期渲染、GlitchPass通道、Element.requestFullscreenDocument.exitFullscreen等。

      效果

      实现效果如banner图所示,页面主体由位于中心的文字网格模型以及四周的圆环面、圆锥以及八面体构成。随着鼠标在页面上移动或点击,模型也随之移动。页面右上角提供了2个按钮,可以切换页面背景色和切换故障风格后期特效。双击屏幕可以进入或退出全屏。

      在线预览:3d-dragonir.vercel.app/#/floating

      或dragonir.github.io/3d/#/floating

      已适配:

      • PC端
      • 移动端

      实现

      资源引入

      首先引入开发所需要的模块资源,其中FontLoader用于加载字体文件,TextGeometry用于创建3D字体网格,EffectComposerRenderPassGlitchPass用于后期特效渲染。

      import * as THREE from "three"; import { FontLoader } from "three/examples/jsm/loaders/FontLoader"; import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'; import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'; import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js';

      DOM结构

      页面DOM结构非常简单,容器#canvas用于场景渲染,.color_pick用于切换页面背景颜色,.pass_button用于切换故障风格后期渲染。

      <div className='floating_page' style={{ backgroundColor: this.state.backgroundColor }}> <div id="canvas"></div> <input className='color_pick' type="color" onChange={this.handleInputChange} value={this.state.backgroundColor} /> <button className='pass_button' onClick={this.handleRenderChange}>特效<span className='highlight'>{this.state.renderGlithPass ? '开' : '关'}</span></button> </div>

      设置状态

      backgroundColor表示当前页面背景色,renderGlithPass表示是否开启后期状态。自测发现在iOS Safari浏览器中,故障风格后期渲染会导致模型产生穿模问题,因此使用该参数控制手机端默认关闭后期效果、pc端默认开启。

      state = { backgroundColor: '#164CCA', renderGlithPass: !(window.navigator.userAgent.toLowerCase().indexOf('mobile') > 0) }

      网格背景

      使用纯CSS属性linear-gradient实现网格背景来美化页面。

      background-image: linear-gradient(rgba(3, 192, 60, .3) 1px, transparent 1px), linear-gradient(90deg, rgba(3, 192, 60, .3) 1px, transparent 1px); background-size: 1em 1em;

      场景初始化

      初始化渲染容器、场景、摄像机,摄像机的位置可根据自身所需调整。render开启alpha并设置.setClearAlpha(0)可将背景色设置为透明。

      canvas = document.getElementById('canvas'); renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setPixelRatio(Math.min(2, window.devicePixelRatio)); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setClearAlpha(0); canvas.appendChild(renderer.domElement); scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, .1, 10000); camera.position.set(-2 * 10000, 0, 780);

      创建材质

      本文中所有网格模型都将使用同一种材质MeshNormalMaterial,应用它的特性,可以使网格模型产生彩色渐变。全局创建一次,后续开发不需要重复创建,有利于页面性能提升。

      const material = new THREE.MeshNormalMaterial();

      MeshNormalMaterial 法向材质

      是一种把法向量映射到RGB颜色的材质,可以通过观察模型表面渐变颜色是否连续来检测模型表面是否平整

      构造函数

      MeshNormalMaterial(parameters : Object)

      parameters:可选,用于定义材质外观的对象,具有一个或多个属性。

      特殊属性

      • .normalMap[Texture]:用于创建法线贴图纹理,RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。
      • .normalMapType[Integer]:法线贴图的类型,选项为THREE.TangentSpaceNormalMap(默认)和THREE.ObjectSpaceNormalMap
      • .normalScale[Vector2]:法线贴图对材质的影响程度。范围是0-1,默认值是Vector2设置为(1, 1)
      • .flatShading[Boolean]:定义材质是否使用平面着色进行渲染,默认值为false
      • .morphNormals[Boolean]:定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为false
      • .morphTargets[Boolean]:定义材质是否使用morphTargets,默认值为false

      创建文字模型

      使用FontLoader加载fontface字体JSON文件,并用TextGeometry创建文字几何体模型。

      const loader = new FontLoader(); loader.load('./fonts/helvetiker_regular.typeface.json', font => { textMesh.geometry = new TextGeometry('@dragonir\nfantastic\nthree.js\nart work', { font: font, size: 100, height: 40, curveSegments: 12, bevelEnabled: true, bevelThickness: 30, bevelSize: 8, bevelOffset: 1, bevelSegments: 12 }); textMesh.material = material; scene.add(textMesh); });

      FontLoader 字体加载器

      使用JSON格式中加载字体的一个类,返回Font, 返回值是表示字体的Shape类型的数组,其内部使用FileLoader来加载文件。

      构造函数

      FontLoader(manager: LoadingManager)

      • manager:加载器所使用的loadingManager,默认值为THREE.DefaultLoadingManager

      方法:

      如何用Three.js React制作长尾词的3D文字悬浮动画效果?

      .loadURL中进行加载,并将被加载的texture传递给onLoad

      • .load(url: String, onLoad: Function, onProgress: Function, onError: Function): null
      • url:文件的URL或者路径,也可以为Data URI
      • onLoad:加载完成时将调用。回调参数是将要被加载的texture
      • onProgress:将在加载过程中进行调用。参数为XMLHttpRequest实例,包含totalloaded字节。
      • onError:加载错误时被调用。

      .parseJSON格式进行解析,并返回一个Font

      • .parse (json: Object ): Font
      • json:用于解析的JSON结构。

      TextGeometry 文本几何体

      用于将文本生成单一几何体的类,它是由一串给定的文本,以及由加载的Font字体和该几何体ExtrudeGeometry父类中的设置所组成的参数构造的。

      构造函数

      TextGeometry(text: String, parameters: Object)

      text:将要显示的文本。

      parameters

      • font[Font]THREE.Font实例。
      • size[Float]:字体大小,默认值为100
      • height[Float]:挤出文本的厚度,默认值为50
      • curveSegments[Integer]:表示文本的曲线上点的数量,默认值为12
      • bevelEnabled[Boolean]:是否开启斜角,默认为false
      • bevelThickness[Float]:文本斜角的深度,默认值为20
      • bevelSize[Float]:斜角与原始文本轮廓之间的延伸距离,默认值为8
      • bevelSegments[Integer]:斜角的分段数,默认值为3

      可以使用facetype.js在线转换Three.js支持的字体。

      创建几何体模型

      使用其他3种内置几何体模型圆环、圆锥和八面体来装饰页面。装饰几何体的数量比较多,为了有效提升页面性能,需要注意以下两点:

      • 使用THREE.Group管理所有几何体。
      • 创建几何体时使用BufferAttribute, 如使用ConeBufferGeometry而不是ConeGeometry,这样可以更有效地将数据传递到GPU

      // 批量创建模型方法 generateRandomMesh = (geometry, material, count) => { for (let i = 0; i < count; i++) { let mesh = new THREE.Mesh(geometry, material); let dist = farDist / 3; let distDouble = dist * 2; // 设置随机的位置和旋转角度 mesh.position.x = Math.random() * distDouble - dist; mesh.position.y = Math.random() * distDouble - dist; mesh.position.z = Math.random() * distDouble - dist; mesh.rotation.x = Math.random() * 2 * Math.PI; mesh.rotation.y = Math.random() * 2 * Math.PI; mesh.rotation.z = Math.random() * 2 * Math.PI; // 手动控制何时重新计算3D变换以获得更好的性能 mesh.matrixAutoUpdate = false; mesh.updateMatrix(); group.add(mesh); } } // 创建100个八面体 const octahedronGeometry = new THREE.OctahedronBufferGeometry(80); generateRandomMesh(octahedronGeometry, material, 100); // 创建200个圆环面 const torusGeometry = new THREE.TorusBufferGeometry(40, 25, 16, 40); generateRandomMesh(torusGeometry, material, 200); // 创建100个圆锥 const coneGeometry = new THREE.ConeBufferGeometry(40, 80, 80); generateRandomMesh(coneGeometry, material, 100); scene.add(group);

      TorusBufferGeometry 圆环缓冲几何体

      用于生成圆环几何体的类。

      构造函数

      TorusBufferGeometry(radius: Float, tube: Float, radialSegments: Integer, tubularSegments: Integer, arc: Float)

      • radius:圆环的半径,从圆环的中心到管道横截面的中心,默认值是1
      • tube:管道的半径,默认值为0.4
      • radialSegments:圆环的分段数,默认值为8
      • tubularSegments:管道的分段数,默认值为6
      • arc:圆环的圆心角,单位是弧度,默认值为Math.PI * 2

      ConeBufferGeometry 圆锥缓冲几何体

      用于生成圆锥几何体的类。

      构造函数

      ConeBufferGeometry(radius: Float, height: Float, radialSegments: Integer, heightSegments: Integer, openEnded: Boolean, thetaStart: Float, thetaLength: Float)

      • radius:圆锥底部的半径,默认值为1
      • height:圆锥的高度,默认值为1
      • radialSegments:圆锥侧面周围的分段数,默认为8
      • heightSegments:圆锥侧面沿着其高度的分段数,默认值为1
      • openEnded:指明该圆锥的底面是开放的还是封顶的。默认值为false,即其底面默认是封顶的。
      • thetaStart:第一个分段的起始角度,默认为0
      • thetaLength:圆锥底面圆扇区的中心角,通常被称为θ。默认值是2*PI,使其成为一个完整的圆锥。

      OctahedronBufferGeometry 八面缓冲几何体

      用于创建八面体的类。

      构造函数

      OctahedronBufferGeometry(radius: Float, detail: Integer)

      • radius:八面体的半径,默认值为1
      • detail:默认值为0,将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个八面体。

      鼠标事件监听

      通过对鼠标移动坐标和模型坐标的相互转换来添加鼠标移动和触摸移动事件的监听方法。

      const mouseFX = { windowHalfX: window.innerWidth / 2, windowHalfY: window.innerHeight / 2, coordinates: (coordX, coordY) => { mouseX = (coordX - mouseFX.windowHalfX) * 5; mouseY = (coordY - mouseFX.windowHalfY) * 5; }, onMouseMove: e => { mouseFX.coordinates(e.clientX, e.clientY) }, onTouchMove: e => { mouseFX.coordinates(e.changedTouches[0].clientX, e.changedTouches[0].clientY)} }; document.addEventListener('mousemove', mouseFX.onMouseMove, false); document.addEventListener('touchmove', mouseFX.onTouchMove, false);

      背景色切换

      使用一个input[type='color']标签来实现背景色切换。

      handleInputChange = e => { this.setState({ backgroundColor: e.target.value }); }

      后期渲染

      为了更具有冲击感的视觉效果,我添加了一个故障风格后期渲染特效,并使用一个按钮开关来控制开启和关闭该特效。

      composer = new EffectComposer(renderer); composer.addPass( new RenderPass(scene, camera)); glitchPass = new GlitchPass(); composer.addPass(glitchPass);

      handleRenderChange = () => { this.setState({ renderGlithPass: !this.state.renderGlithPass }); }

      后期渲染

      Three.js后期渲染处理,是通过叠加渲染通道达到预期视觉效果的过程。实现流程如下:

      • 创建效果组合器:效果组合器是各种处理通道的入口,使用EffectComposer对象创建一个效果组合器。
      • 添加通道:添加RenderPass通道 它将在指定的场景和相机的基础上渲染出一个新的场景。
      • 组合器更新:在动画循环中,调用效果组合器的render方法,通道生成效果将在场景中输出。

      GlitchPass 故障风格通道

      GlitchPass通道产生模拟故障风格效果,它只有一个可选配置参数:

      goWild该属性接收一个布尔值,指定是否持续产生电磁风暴效果。

      Three.js提供了很多后期处理的通道,可以直接使用。同时提供了ShaderPass通道,它支持使用自定义Shader,可以创建高级的自定义后期处理通道。

      动画

      requestAnimationFrame中更新场景、相机、和后期渲染通道。

      function animate() { requestAnimationFrame(animate); camera.position.x += (mouseX - camera.position.x) * 0.05; camera.position.y += (mouseY * -1 - camera.position.y) * 0.05; camera.lookAt(scene.position); // 给场景中的立方体网格和字体网格添加自转动画 const t = Date.now() * 0.001; const rx = Math.sin(t * 0.7) * 0.5; const ry = Math.sin(t * 0.3) * 0.5; const rz = Math.sin(t * 0.2) * 0.5; group.rotation.x = rx; group.rotation.y = ry; group.rotation.z = rz; textMesh.rotation.x = rx; textMesh.rotation.y = ry; textMesh.rotation.z = rx; renderer.render(scene, camera); // 更新后期渲染通道 composer.render(); }

      缩放适配

      renderercomposer大小要同时调整。

      window.addEventListener('resize', () => { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); composer.setSize( window.innerWidth, window.innerHeight ); }, false);

      双击全屏

      监听页面鼠标双击dblclick事件,通过调用requestFullscreenexitFullscreen进入或退出全屏状态。

      window.addEventListener('dblclick', () => { let fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement; if (!fullscreenElement) { if (canvas.requestFullscreen) { canvas.requestFullscreen(); } else if (canvas.webkitRequestFullscreen) { canvas.webkitRequestFullscreen(); } console.log('进入全屏') } else { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } console.log('退出全屏') } })

      Element.requestFullscreen

      Element.requestFullscreen方法用于发出异步请求使元素进入全屏模式。调用此API并不能保证元素一定能够进入全屏模式。如果元素被允许进入全屏幕模式,返回的Promiseresolve,并且该元素会收到一个fullscreenchange事件,通知它已经进入全屏模式。如果全屏请求被拒绝,返回的promise会变成rejected并且该元素会收到一个fullscreenerror事件。如果该元素已经从原来的文档中分离,那么该文档将会收到这些事件。

      语法

      var Promise = Element.requestFullscreen(options);

      options:可选,一个FullscreenOptions对象提供切换到全屏模式的控制选项。

      这个方法只能在用户交互或者设备方向改变的时候调用,否则将会失败。FullscreenOptions目前唯一的选项是navigationUI,这控制了是否在元素处于全屏模式时显示导航条UI。默认值是auto,表明这将由浏览器来决定是否显示导航条。

      Document.exitFullscreen

      Document.exitFullscreen方法用于让当前文档退出全屏模式。调用这个方法会让文档回退到上一个调用Element.requestFullscreen方法进入全屏模式之前的状态。

      语法

      document.exitFullscreen();

      到此,示例页面的全部功能都完成了,可访问以下链接查看完整代码。

      完整代码:github.com/dragonir/3d/tree/master/src/containers/Floating

      总结

      本文知识点主要包含的的新知识:

      • CSS网格背景
      • MeshNormalMaterial法向材质
      • FontLoader字体加载器
      • TextGeometry文本缓冲几何体
      • TorusBufferGeometry圆环缓冲几何体
      • ConeBufferGeometry圆锥缓冲几何体
      • OctahedronBufferGeometry八面缓冲几何体
      • Three.js后期渲染
      • GlitchPass通道
      • Element.requestFullscreen
      • Document.exitFullscreen

      以上就是Three.js+React实现3D文字悬浮效果的详细内容,更多关于Three.js React文字悬浮的资料请关注自由互联其它相关文章!