Skip to content

Commit

Permalink
feat: 🌟浮动字体效果页面文章文案优化、配置vercel.
Browse files Browse the repository at this point in the history
  • Loading branch information
dragonir committed Mar 9, 2022
1 parent 6915a96 commit fd48e30
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vercel
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
"deploy": "gh-pages -d build",
"vercel": "vercel --prod"
},
"eslintConfig": {
"extends": [
Expand Down
99 changes: 52 additions & 47 deletions src/containers/Floating/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
# 使用Three.js实现神奇的的3D文字悬浮效果
# 使用Three.js实现神奇的3D文字悬浮效果

![banner](./images/banner.gif)

> 声明:本文涉及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修改、非法传播、转载、出版、商用、及进行其他获利行为。
## 背景

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

## 效果

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

![mobile](./images/mobile.png)

> `👀` 在线预览:<https://dragonir.github.io/3d/#/floating>
> `👀` 在线预览:<https://3d-dragonir.vercel.app/#/floating>
> `👀`<https://dragonir.github.io/3d/#/floating>
已适配:

Expand All @@ -36,10 +37,10 @@ import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js';
```

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

### DOM结构

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

```html
<div className='floating_page' style={{ backgroundColor: this.state.backgroundColor }}>
<div id="canvas"></div>
Expand All @@ -48,7 +49,9 @@ import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js';
</div>
```

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

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

```js
state = {
Expand All @@ -59,7 +62,7 @@ state = {

### 网格背景

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

```css
background-image: linear-gradient(rgba(3, 192, 60, .3) 1px, transparent 1px), linear-gradient(90deg, rgba(3, 192, 60, .3) 1px, transparent 1px);
Expand All @@ -68,7 +71,7 @@ background-size: 1em 1em;

### 场景初始化

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

```js
canvas = document.getElementById('canvas');
Expand All @@ -84,7 +87,7 @@ camera.position.set(-2 * 10000, 0, 780);

### 创建材质

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

```js
const material = new THREE.MeshNormalMaterial();
Expand All @@ -104,16 +107,16 @@ MeshNormalMaterial(parameters : Object)

**特殊属性**

* `.normalMap[Texture]`:用于创建法线贴图纹理`RGB` 值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。
* `.normalMapType[Integer]`:法线贴图的类型选项为 `THREE.TangentSpaceNormalMap`(默认)和 `THREE.ObjectSpaceNormalMap`
* `.normalScale[Vector2]`:法线贴图对材质的影响程度。范围是 `0-1`默认值是 `Vector2` 设置为 `(1, 1)`
* `.flatShading[Boolean]`:定义材质是否使用平面着色进行渲染默认值为 `false`
* `.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`
* `.morphTargets[Boolean]`:定义材质是否使用 `morphTargets`默认值为 `false`

### 创建文字模型

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

```js
const loader = new FontLoader();
Expand Down Expand Up @@ -146,7 +149,7 @@ loader.load('./fonts/helvetiker_regular.typeface.json', font => {
FontLoader(manager: LoadingManager)
```

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

`方法`

Expand All @@ -155,14 +158,14 @@ FontLoader(manager: LoadingManager)
* `url`:文件的URL或者路径,也可以为 `Data URI`
* `onLoad`:加载完成时将调用。回调参数是将要被加载的 `texture`
* `onProgress`:将在加载过程中进行调用。参数为 `XMLHttpRequest` 实例,包含 `total``loaded` 字节。
* `onError`在加载错误时被调用
* `onError`加载错误时被调用
* `.parse``JSON` 格式进行解析,并返回一个 `Font`
* `.parse (json: Object ): Font`
* `json`:用于解析的 `JSON` 结构。

#### `💡` TextGeometry 文本几何体

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

**构造函数**

Expand All @@ -187,8 +190,8 @@ TextGeometry(text: String, parameters: Object)

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

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

```js
// 批量创建模型方法
Expand Down Expand Up @@ -271,6 +274,25 @@ OctahedronBufferGeometry(radius: Float, detail: Integer)
* `radius`:八面体的半径,默认值为 `1`
* `detail`:默认值为 `0`,将这个值设为一个大于 `0` 的数将会为它增加一些顶点,使其不再是一个八面体。

### 鼠标事件监听

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

```js
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);
```

![preview_1](./images/preview_1.gif)

### 背景色切换
Expand All @@ -287,7 +309,7 @@ handleInputChange = e => {

### 后期渲染

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

```js
composer = new EffectComposer(renderer);
Expand Down Expand Up @@ -320,25 +342,6 @@ handleRenderChange = () => {

> `📌` `Three.js` 提供了很多后期处理的通道,可以直接使用。同时提供了 `ShaderPass` 通道,它支持使用自定义 `Shader`,可以创建高级的自定义后期处理通道。
### 鼠标事件监听

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

```js
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);
```

### 动画

`requestAnimationFrame` 中更新场景、相机、和后期渲染通道。
Expand Down Expand Up @@ -368,6 +371,8 @@ function animate() {

### 缩放适配

`renderer``composer` 大小要同时调整。

```js
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
Expand All @@ -379,7 +384,7 @@ window.addEventListener('resize', () => {

### 双击全屏

监听页面双击 `dblclick` 事件,通过调用 `requestFullscreen``exitFullscreen` 进入或退出全屏状态。
监听页面 `🖱` 双击 `dblclick` 事件,通过调用 `requestFullscreen``exitFullscreen` 进入或退出全屏状态。

```js
window.addEventListener('dblclick', () => {
Expand Down Expand Up @@ -418,15 +423,15 @@ var Promise = Element.requestFullscreen(options);
#### `💡` Document.exitFullscreen

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

**语法**

```js
document.exitFullscreen();
```

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

> `🔗` 完整代码:<https://github.com/dragonir/3d/tree/master/src/containers/Floating>
Expand All @@ -450,13 +455,13 @@ document.exitFullscreen();
## 附录

* [1]. [拜托,使用Three.js让二维图片具有3D效果超酷的好吗 💥](https://juejin.cn/post/7067344398912061454)
* [1]. [Three.js 实现让二维图片具有3D效果](https://juejin.cn/post/7067344398912061454)
* [2]. [Three.js 实现2022冬奥主题3D趣味页面,冰墩墩 🐼](https://juejin.cn/post/7060292943608807460)
* [3]. [Three.js 制作一个专属3D奖牌 🥇](https://juejin.cn/post/7055079293247815711)
* [3]. [Three.js 制作一个专属3D奖牌](https://juejin.cn/post/7055079293247815711)
* [4]. [Three.js 实现虎年春节3D创意页面](https://juejin.cn/post/7051745314914435102)
* [5]. [Three.js 实现脸书元宇宙3D动态Logo](https://juejin.cn/post/7031893833163997220)
* [6]. [Three.js 实现3D全景侦探小游戏](https://juejin.cn/post/7042298964468564005)
* [7]. [Three.js实现炫酷的酸性风格3D页面](https://juejin.cn/post/7012996721693163528)
* [7]. [Three.js 实现炫酷的酸性风格3D页面](https://juejin.cn/post/7012996721693163528)
* [8]. [www.ilithya.rocks](https://www.ilithya.rocks/)
* [9]. [MDN requestFullScreen](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/requestFullScreen)
* [10]. [MDN exitFullscreen](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/exitFullscreen)

0 comments on commit fd48e30

Please sign in to comment.