怎么用Three.js+React实现3D文字悬浮效果
设置状态
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,transparent1px),linear-gradient(90deg,rgba(3,192,60,.3)1px,transparent1px);background-size:1em1em;
场景初始化
初始化渲染容器、场景、摄像机,摄像机的位置可根据自身所需调整。render
开启alpha
并设置.setClearAlpha(0)
可将背景色设置为透明。
canvas=document.getElementById('canvas');renderer=newTHREE.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=newTHREE.Scene();camera=newTHREE.PerspectiveCamera(70,window.innerWidth/window.innerHeight,.1,10000);camera.position.set(-2*10000,0,780);
创建材质
本文中所有网格模型都将使用同一种材质MeshNormalMaterial
,应用它的特性,可以使网格模型产生彩色渐变。全局创建一次,后续开发不需要重复创建,有利于页面性能提升。
constmaterial=newTHREE.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
创建文字几何体模型。
constloader=newFontLoader();loader.load('./fonts/helvetiker_regular.typeface.json',font=>{textMesh.geometry=newTextGeometry('@dragonir\nfantastic\nthree.js\nartwork',{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
。
方法:
.load
从URL
中进行加载,并将被加载的texture
传递给onLoad
。
.load(url: String, onLoad: Function, onProgress: Function, onError: Function): null
。url
:文件的URL或者路径,也可以为Data URI
。onLoad
:加载完成时将调用。回调参数是将要被加载的texture
。onProgress
:将在加载过程中进行调用。参数为XMLHttpRequest
实例,包含total
和loaded
字节。onError
:加载错误时被调用。
.parse
以JSON
格式进行解析,并返回一个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(leti=0;i TorusBufferGeometry 圆环缓冲几何体 用于生成圆环几何体的类。 构造函数: TorusBufferGeometry(radius:Float,tube:Float,radialSegments:Integer,tubularSegments:Integer,arc:Float) ConeBufferGeometry 圆锥缓冲几何体 用于生成圆锥几何体的类。 构造函数: ConeBufferGeometry(radius:Float,height:Float,radialSegments:Integer,heightSegments:Integer,openEnded:Boolean,thetaStart:Float,thetaLength:Float) OctahedronBufferGeometry 八面缓冲几何体 用于创建八面体的类。 构造函数: OctahedronBufferGeometry(radius:Float,detail:Integer) 通过对鼠标移动坐标和模型坐标的相互转换来添加鼠标移动和触摸移动事件的监听方法。 constmouseFX={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); 使用一个 handleInputChange=e=>{this.setState({backgroundColor:e.target.value});} 为了更具有冲击感的视觉效果,我添加了一个故障风格后期渲染特效,并使用一个按钮开关来控制开启和关闭该特效。 composer=newEffectComposer(renderer);composer.addPass(newRenderPass(scene,camera));glitchPass=newGlitchPass();composer.addPass(glitchPass); handleRenderChange=()=>{this.setState({renderGlithPass:!this.state.renderGlithPass});} 后期渲染 创建效果组合器:效果组合器是各种处理通道的入口,使用 添加通道:添加 组合器更新:在动画循环中,调用效果组合器的 GlitchPass 故障风格通道 在 functionanimate(){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);//给场景中的立方体网格和字体网格添加自转动画constt=Date.now()*0.001;constrx=Math.sin(t*0.7)*0.5;constry=Math.sin(t*0.3)*0.5;constrz=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();} window.addEventListener('resize',()=>{camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);composer.setSize(window.innerWidth,window.innerHeight);},false); 监听页面鼠标双击 window.addEventListener('dblclick',()=>{letfullscreenElement=document.fullscreenElement||document.webkitFullscreenElement;if(!fullscreenElement){if(canvas.requestFullscreen){canvas.requestFullscreen();}elseif(canvas.webkitRequestFullscreen){canvas.webkitRequestFullscreen();}console.log('进入全屏')}else{if(document.exitFullscreen){document.exitFullscreen();}elseif(document.webkitExitFullscreen){document.webkitExitFullscreen();}console.log('退出全屏')}}) Element.requestFullscreen 语法: varPromise=Element.requestFullscreen(options); 这个方法只能在用户交互或者设备方向改变的时候调用,否则将会失败。 Document.exitFullscreen 语法: document.exitFullscreen(); “怎么用Three.js+React实现3D文字悬浮效果”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注恰卡编程网网站,小编将为大家输出更多高质量的实用文章!radius
:圆环的半径,从圆环的中心到管道横截面的中心,默认值是1
。tube
:管道的半径,默认值为0.4
。radialSegments
:圆环的分段数,默认值为8
。tubularSegments
:管道的分段数,默认值为6
。arc
:圆环的圆心角,单位是弧度,默认值为Math.PI * 2
。radius
:圆锥底部的半径,默认值为1
。height
:圆锥的高度,默认值为1
。radialSegments
:圆锥侧面周围的分段数,默认为8
。heightSegments
:圆锥侧面沿着其高度的分段数,默认值为1
。openEnded
:指明该圆锥的底面是开放的还是封顶的。默认值为false
,即其底面默认是封顶的。thetaStart
:第一个分段的起始角度,默认为0
。thetaLength
:圆锥底面圆扇区的中心角,通常被称为θ
。默认值是2*PI
,使其成为一个完整的圆锥。radius
:八面体的半径,默认值为1
。detail
:默认值为0
,将这个值设为一个大于0
的数将会为它增加一些顶点,使其不再是一个八面体。鼠标事件监听
背景色切换
input[type='color']
标签来实现背景色切换。后期渲染
Three.js
后期渲染处理,是通过叠加渲染通道达到预期视觉效果的过程。实现流程如下:EffectComposer
对象创建一个效果组合器。RenderPass
通道 它将在指定的场景和相机的基础上渲染出一个新的场景。render
方法,通道生成效果将在场景中输出。GlitchPass
通道产生模拟故障风格效果,它只有一个可选配置参数:goWild
该属性接收一个布尔值,指定是否持续产生电磁风暴效果。Three.js
提供了很多后期处理的通道,可以直接使用。同时提供了ShaderPass
通道,它支持使用自定义Shader
,可以创建高级的自定义后期处理通道。动画
requestAnimationFrame
中更新场景、相机、和后期渲染通道。缩放适配
renderer
和composer
大小要同时调整。双击全屏
dblclick
事件,通过调用requestFullscreen
和exitFullscreen
进入或退出全屏状态。Element.requestFullscreen
方法用于发出异步请求使元素进入全屏模式。调用此API
并不能保证元素一定能够进入全屏模式。如果元素被允许进入全屏幕模式,返回的Promise
会resolve
,并且该元素会收到一个fullscreenchange
事件,通知它已经进入全屏模式。如果全屏请求被拒绝,返回的promise
会变成rejected
并且该元素会收到一个fullscreenerror
事件。如果该元素已经从原来的文档中分离,那么该文档将会收到这些事件。options
:可选,一个FullscreenOptions
对象提供切换到全屏模式的控制选项。FullscreenOptions
目前唯一的选项是navigationUI
,这控制了是否在元素处于全屏模式时显示导航条UI
。默认值是auto
,表明这将由浏览器来决定是否显示导航条。Document.exitFullscreen
方法用于让当前文档退出全屏模式。调用这个方法会让文档回退到上一个调用Element.requestFullscreen
方法进入全屏模式之前的状态。