激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - js教程 - three.js如何實現3D動態文字效果

three.js如何實現3D動態文字效果

2022-01-25 16:33alphardex js教程

這篇文章主要給大家介紹了關于three.js如何實現3D動態文字效果的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

大家好,這里是 CSS 魔法使――alphardex。

之前在逛國外網站的時候,發現有些網站的文字是刻在3D圖形上的,并且能在圖形上運動,視覺效果相當不錯,于是筆者就也想用three.js來嘗試復現出這種效果

three.js如何實現3D動態文字效果

上圖只是所有效果的其中之一,接下來讓我們一起開干吧~

準備工作

筆者自行封裝的three.js模板:Three.js Starter

讀者可以點擊右下角fork一份后再開始本項目

本項目需要用到位圖字體,可以直接復制demo的HTML里的font字體代碼

一個注意點:three-bmfont-text這個庫依賴全局的three.js,因此要在JS里額外引入一次three.js,如下圖

three.js如何實現3D動態文字效果

實現思路

  1. 加載位圖字體文件,將其轉化為文字對象所需要的形狀和材質
  2. 創建文字對象
  3. 創建渲染目標,可以理解為canvas中的canvas,因為接下來我們要將文字對象本身當做貼圖
  4. 創建承載字體的容器,將文字對象作為貼圖貼上去
  5. 動畫

正片

搭好架子

<div class="relative w-screen h-screen">
 <div class="kinetic-text w-full h-full bg-blue-1"></div>
 <div class="font">
 <font>
  一坨從demo里CV而來的字體代碼
 </font>
 </div>
</div>
:root {
 --blue-color-1: #2c3e50;
}

.bg-blue-1 {
 background: var(--blue-color-1);
}
import createGeometry from "https://cdn.skypack.dev/three-bmfont-text@3.0.1";
import MSDFShader from "https://cdn.skypack.dev/three-bmfont-text@3.0.1/shaders/msdf";
import parseBmfontXml from "https://cdn.skypack.dev/parse-bmfont-xml@1.1.4";

const font = parseBmfontXml(document.querySelector(".font").innerHTML);
const fontAtlas = "https://i.loli.net/2021/02/20/DcEhuYNjxCgeU42.png";

const kineticTextTorusKnotVertexShader = `(頂點著色器代碼,先空著,具體見下文)`;

const kineticTextTorusKnotFragmentShader = `(片元著色器代碼,先空著,具體見下文)`;

class KineticText extends Base {
 constructor(sel: string, debug: boolean) {
 super(sel, debug);
 this.cameraPosition = new THREE.Vector3(0, 0, 4);
 this.clock = new THREE.Clock();
 this.meshConfig = {
  torusKnot: {
  vertexShader: kineticTextTorusKnotVertexShader,
  fragmentShader: kineticTextTorusKnotFragmentShader,
  geometry: new THREE.TorusKnotGeometry(9, 3, 768, 3, 4, 3)
  }
 };
 this.meshNames = Object.keys(this.meshConfig);
 this.params = {
  meshName: "torusKnot",
  velocity: 0.5,
  shadow: 5,
  color: "#000000",
  frequency: 0.5,
  text: "ALPHARDEX",
  cameraZ: 2.5
 };
 }
 // 初始化
 async init() {
 this.createScene();
 this.createPerspectiveCamera();
 this.createRenderer(true);
 await this.createKineticText(this.params.text);
 this.createLight();
 this.createOrbitControls();
 this.addListeners();
 this.setLoop();
 }
 // 創建動態文字
 async createKineticText(text: string) {
 await this.createFontText(text);
 this.createRenderTarget();
 this.createTextContainer();
 }
}

加載和創建字體

首先加載字體文件,并創建出形狀和材質,有了這兩樣就能創建出字體對象了

class KineticText extends Base {
 loadFontText(text: string): any {
 return new Promise((resolve) => {
  const fontGeo = createGeometry({
  font,
  text
  });
  const loader = new THREE.TextureLoader();
  loader.load(fontAtlas, (texture) => {
  const fontMat = new THREE.RawShaderMaterial(
   MSDFShader({
   map: texture,
   side: THREE.DoubleSide,
   transparent: true,
   negate: false,
   color: 0xffffff
   })
  );
  resolve({ fontGeo, fontMat });
  });
 });
 }
 async createFontText(text: string) {
 const { fontGeo, fontMat } = await this.loadFontText(text);
 const textMesh = this.createMesh({
  geometry: fontGeo,
  material: fontMat
 });
 textMesh.position.set(-0.965, -0.525, 0);
 textMesh.rotation.set(ky.deg2rad(180), 0, 0);
 textMesh.scale.set(0.008, 0.025, 1);
 this.textMesh = textMesh;
 }
}

著色器

頂點著色器

通用模板,直接CV即可

varying vec2 vUv;
varying vec3 vPosition;

void main(){
 vec4 modelPosition=modelMatrix*vec4(position,1.);
 vec4 viewPosition=viewMatrix*modelPosition;
 vec4 projectedPosition=projectionMatrix*viewPosition;
 gl_Position=projectedPosition;
 
 vUv=uv;
 vPosition=position;
}

片元著色器

利用fract函數創建重復的貼圖,加上位移距離displacement使得貼圖能隨著時間的增加而動起來,再用clamp函數來根據z軸大小限定陰影的范圍,意思是離畫面越遠則陰影越重,反之離畫面越近則陰影越輕

uniform sampler2D uTexture;
uniform float uTime;
uniform float uVelocity;
uniform float uShadow;

varying vec2 vUv;
varying vec3 vPosition;

void main(){
 vec2 repeat=vec2(12.,3.);
 vec2 repeatedUv=vUv*repeat;
 vec2 displacement=vec2(uTime*uVelocity,0.);
 vec2 uv=fract(repeatedUv+displacement);
 vec3 texture=texture2D(uTexture,uv).rgb;
 // texture*=vec3(uv.x,uv.y,1.);
 float shadow=clamp(vPosition.z/uShadow,0.,1.);// farther darker (to 0).
 vec3 color=vec3(texture*shadow);
 gl_FragColor=vec4(color,1.);
}

此時文本顯示到了屏幕上

創建渲染目標

為了將字體對象本身作為貼圖,創建了一個渲染目標

class KineticText extends Base {
 createRenderTarget() {
 const rt = new THREE.WebGLRenderTarget(
  window.innerWidth,
  window.innerHeight
 );
 this.rt = rt;
 const rtCamera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000);
 rtCamera.position.z = this.params.cameraZ;
 this.rtCamera = rtCamera;
 const rtScene = new THREE.Scene();
 rtScene.add(this.textMesh);
 this.rtScene = rtScene;
 }
}

創建字體容器

創建一個容器,并將字體對象本身作為貼圖貼上去,再應用動畫即可完成

class KineticText extends Base {
 createTextContainer() {
 if (this.mesh) {
  this.scene.remove(this.mesh);
  this.mesh = null;
  this.material!.dispose();
  this.material = null;
 }
 this.rtScene.background = new THREE.Color(this.params.color);
 const meshConfig = this.meshConfig[this.params.meshName];
 const geometry = meshConfig.geometry;
 const material = new THREE.ShaderMaterial({
  vertexShader: meshConfig.vertexShader,
  fragmentShader: meshConfig.fragmentShader,
  uniforms: {
  uTime: {
   value: 0
  },
  uVelocity: {
   value: this.params.velocity
  },
  uTexture: {
   value: this.rt.texture
  },
  uShadow: {
   value: this.params.shadow
  },
  uFrequency: {
   value: this.params.frequency
  }
  }
 });
 this.material = material;
 const mesh = this.createMesh({
  geometry,
  material
 });
 this.mesh = mesh;
 }
 update() {
 if (this.rtScene) {
  this.renderer.setRenderTarget(this.rt);
  this.renderer.render(this.rtScene, this.rtCamera);
  this.renderer.setRenderTarget(null);
 }
 const elapsedTime = this.clock.getElapsedTime();
 if (this.material) {
  this.material.uniforms.uTime.value = elapsedTime;
 }
 }
}

別忘了把相機調遠一些

this.cameraPosition = new THREE.Vector3(0, 0, 40);

風騷的動態文字出現了:)

three.js如何實現3D動態文字效果

項目地址

Kinetic Text

demo里不止本文創建的這一種形狀,大家可以隨意把玩。

總結

到此這篇關于three.js如何實現3D動態文字效果的文章就介紹到這了,更多相關three.js 3D動態文字內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/6931647184349691911

延伸 · 閱讀

精彩推薦
  • js教程Javascript實現漢字和拼音互轉的終極方案

    Javascript實現漢字和拼音互轉的終極方案

    網上關于JS實現漢字和拼音互轉的文章很多,但是比較雜亂,有的不支持多音字、不支持聲調或者字典文件太大,無法根據實際需要滿足需求。這篇文章給...

    我是小茗同學10352021-12-15
  • js教程詳解微信小程序軌跡回放實現及遇到的坑

    詳解微信小程序軌跡回放實現及遇到的坑

    這篇文章主要介紹了詳解微信小程序軌跡回放實現及遇到的坑,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要...

    Keen6092022-01-12
  • js教程詳解uniapp的全局變量實現方式

    詳解uniapp的全局變量實現方式

    這篇文章主要介紹了詳解uniapp的全局變量實現方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下...

    繭君10922021-12-29
  • js教程原生js拖拽功能制作滑動條實例代碼

    原生js拖拽功能制作滑動條實例代碼

    這篇文章主要介紹了原生js拖拽功能制作滑動條實例教程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的...

    蔣偉平3452022-01-17
  • js教程ES6字符串的擴展實例

    ES6字符串的擴展實例

    這篇文章主要介紹了ES6字符串的擴展實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小...

    知否5552021-12-16
  • js教程ES6的循環與可迭代對象示例詳解

    ES6的循環與可迭代對象示例詳解

    這篇文章主要給大家介紹了關于ES6的循環與可迭代對象的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    瘋狂的技術宅11542022-01-12
  • js教程three.js 實現露珠滴落動畫效果的示例代碼

    three.js 實現露珠滴落動畫效果的示例代碼

    這篇文章主要介紹了three.js 實現露珠滴落動畫效果的示例代碼,非常不錯,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下...

    稀土掘金11192022-01-24
  • js教程原生JavaScript實現購物車

    原生JavaScript實現購物車

    這篇文章主要為大家詳細介紹了原生JavaScript實現購物車,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    棟棟很優秀啊4362021-12-29
主站蜘蛛池模板: 免费国产成人高清在线看软件 | 国产精品久久久久久久久久东京 | 99久久九九爱看免费直播 | 久久久久久久91 | 精品久久久久久久久久久久包黑料 | 国产成人精品区一区二区不卡 | 国产精品a一 | 亚洲一区 国产精品 | 可以看毛片的网址 | 久久艹一区 | 夜间福利视频 | h视频免费在线 | 91看片免费在线观看 | 久久精品视频一区二区三区 | 日本韩国欧美一级片 | 久草在线观看资源 | 少妇一级淫片免费放播放 | 日韩黄色片免费看 | 欧美日韩国产综合网 | 国产人成精品综合欧美成人 | 黄网站免费观看视频 | hdhdhd69ⅹxxx黑人 | 中国杭州少妇xxxx做受 | 4p一女两男做爰在线观看 | 精品欧美一区二区精品久久小说 | 国毛片| 亚洲午夜在线 | 日韩精品久久久久久久电影99爱 | 亚洲免费视 | 99国产精品国产免费观看 | 欧美视频在线观看一区 | 欧美精品成人一区二区在线观看 | 欧美日本色 | 欧美1区2区 | 黄网站免费观看视频 | 97久久人人超碰caoprom | 久久久成人999亚洲区美女 | 免费在线观看亚洲 | 性看小视频 | 在线天堂中文字幕 | av色在线观看 |