three.js で 3D ダイナミック テキスト効果を実現する方法

three.js で 3D ダイナミック テキスト効果を実現する方法

序文

みなさんこんにちは。CSS ウィザードの alphardex です。

以前、海外のウェブサイトを閲覧していたとき、いくつかのウェブサイトのテキストが 3D グラフィックに刻まれていて、グラフィック上を動かせることに気づきました。視覚効果がかなり良かったので、私も three.js を使ってこの効果を再現したいと思いました。

上の写真はエフェクトの 1 つにすぎません。それでは始めましょう。

準備

私が自分でパッケージ化した three.js テンプレート: Three.js Starter

読者は、このプロジェクトを始める前に右下隅をクリックしてコピーをフォークすることができます。

このプロジェクトにはビットマップ フォントが必要です。デモの HTML でフォント コードを直接コピーできます。

注意: three-bmfont-text ライブラリはグローバルの three.js に依存しているため、以下に示すように、JS で three.js をもう一度インポートする必要があります。

実装のアイデア

  1. ビットマップフォントファイルを読み込み、テキストオブジェクトに必要な形状とマテリアルに変換します。
  2. テキストオブジェクトの作成
  3. レンダリングターゲットを作成します。これはキャンバス内のキャンバスとして理解できます。次にテキストオブジェクト自体をテクスチャとして使用します。
  4. フォントを保持するコンテナを作成し、テキストオブジェクトをテクスチャとして貼り付けます。
  5. アニメーション

ポジティブ

足場を設置する

<div class="相対的なw-screen h-screen">
 <div class="kinetic-text w-full h-full bg-blue-1"></div>
 <div class="font">
 <フォント>
  デモ CV からのフォント コード一式</font>
 </div>
</div>
:根 {
 --青色1: #2c3e50;
}

.bg-blue-1 {
 背景: var(--blue-color-1);
}
「https://cdn.skypack.dev/[email protected]」からcreateGeometryをインポートします。
「https://cdn.skypack.dev/[email protected]/shaders/msdf」からMSDFShaderをインポートします。
「https://cdn.skypack.dev/[email protected]」からparseBmfontXmlをインポートします。

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

const kineticTextTorusKnotVertexShader = `(頂点シェーダーコード、今のところ空、詳細は下記を参照)`;

const kineticTextTorusKnotFragmentShader = `(フラグメント シェーダー コード、現在は空、詳細は以下を参照)`;

クラスKineticTextはBaseを拡張します{
 コンストラクタ(sel: 文字列、debug: ブール値) {
 スーパー(sel、デバッグ);
 this.cameraPosition = 新しい THREE.Vector3(0, 0, 4);
 this.clock = 新しい THREE.Clock();
 this.meshConfig = {
  トーラスノット:
  頂点シェーダー: キネティックテキストトーラスノット頂点シェーダー、
  フラグメントシェーダー: キネティックテキストトーラスノットフラグメントシェーダー、
  ジオメトリ: 新しい THREE.TorusKnotGeometry(9, 3, 768, 3, 4, 3)
  }
 };
 this.meshNames = Object.keys(this.meshConfig);
 this.params = {
  メッシュ名: "torusKnot",
  速度: 0.5、
  影: 5,
  色: "#000000",
  頻度: 0.5、
  テキスト: "ALPHARDEX",
  カメラZ: 2.5
 };
 }
 // 初期化 async init() {
 シーンを作成します。
 パースペクティブカメラを作成します。
 レンダラーを作成します。
 this.createKineticText(this.params.text); を待機します。
 this.createLight();
 オービットコントロールを作成します。
 リスナーを追加します。
 ループを設定します。
 }
 // 動的テキストを作成する async createKineticText(text: string) {
 this.createFontText(テキスト) を待機します。
 RenderTarget を作成します。
 テキストコンテナを作成します。
 }
}

フォントの読み込みと作成

まずはフォントファイルを読み込み、シェイプとマテリアルを作成します。この2つがあればフォントオブジェクトを作成できます。

クラスKineticTextはBaseを拡張します{
 loadFontText(テキスト: 文字列): 任意 {
 新しいPromise((resolve) => {を返す
  const fontGeo = createGeometry({
  フォント、
  文章
  });
  const ローダー = 新しい THREE.TextureLoader();
  loader.load(fontAtlas, (テクスチャ) => {
  const fontMat = 新しい THREE.RawShaderMaterial(
   MSDFシェーダー({
   マップ: テクスチャ、
   サイド: THREE.DoubleSide、
   透明: true、
   否定: 偽、
   色: 0xffffff
   })
  );
  解決します({ fontGeo, fontMat });
  });
 });
 }
 非同期createFontText(テキスト: 文字列) {
 const { fontGeo, fontMat } = this.loadFontText(text); を待機します。
 定数textMesh = this.createMesh({
  ジオメトリ: fontGeo、
  マテリアル:フォントマット
 });
 テキストメッシュの位置を設定します(-0.965, -0.525, 0);
 テキストメッシュの回転を設定します(ky.deg2rad(180), 0, 0);
 テキストメッシュのスケールを設定します(0.008, 0.025, 1);
 テキストメッシュを作成します。
 }
}

シェーダー

頂点シェーダー

ユニバーサルテンプレート、履歴書のみ使用

変化するvec2 vUv;
vec3 vPosition を変更する;

void main(){
 vec4 モデル位置 = modelMatrix*vec4(位置、1.);
 vec4 ビュー位置 = ビューマトリックス * モデル位置;
 vec4 投影位置 = 投影マトリックス * ビュー位置;
 gl_Position = 投影された位置;
 
 uv = uv;
 vPosition=位置;
}

フラグメントシェーダー

fract関数を使用して繰り返しテクスチャを作成し、変位を追加してテクスチャが時間の経過とともに動くようにし、clamp関数を使用してZ軸のサイズに応じて影の範囲を制限します。つまり、画面から遠いほど影が濃くなり、逆に画面に近いほど影が薄くなります。

均一サンプラー2D uTexture;
ユニフォーム float uTime;
均一な浮動小数点値の uVelocity;
均一な float uShadow;

変化するvec2 vUv;
vec3 vPosition を変更する;

void main(){
 vec2繰り返し = vec2(12.,3.);
 vec2 繰り返しUv = vUv * 繰り返し;
 vec2変位=vec2(uTime*uVelocity,0.);
 vec2 uv=fract(繰り返しUv+変位);
 vec3 テクスチャ = texture2D(uTexture,uv).rgb;
 // テクスチャ*=vec3(uv.x,uv.y,1.);
 float shadow = clamp (vPosition.z / uShadow, 0., 1.); // さらに暗くなります (0 まで)。
 vec3 色 = vec3(テクスチャ*シャドウ);
 gl_FragColor = vec4(色,1.);
}

テキストが画面に表示されます

レンダリングターゲットの作成

フォントオブジェクト自体をテクスチャとして使用するには、レンダリングターゲットを作成します。

クラスKineticTextはBaseを拡張します{
 レンダーターゲットを作成します(){
 const rt = 新しい THREE.WebGLRenderTarget(
  ウィンドウの内側の幅、
  ウィンドウの内側の高さ
 );
 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;
 }
}

フォントコンテナの作成

コンテナを作成し、フォントオブジェクト自体をテクスチャとしてアタッチし、アニメーションを適用して完成させます。

クラスKineticTextはBaseを拡張します{
 テキストコンテナを作成します(){
 if (this.mesh) {
  this.scene.remove(this.mesh);
  this.mesh = null;
  this.material!.dispose();
  this.material = null;
 }
 this.rtScene.background = 新しい THREE.Color(this.params.color);
 const meshConfig = this.meshConfig[this.params.meshName];
 const ジオメトリ = meshConfig.geometry;
 const マテリアル = 新しい THREE.ShaderMaterial({
  頂点シェーダー: meshConfig.vertexShader、
  フラグメントシェーダー: meshConfig.fragmentShader、
  制服:
  u時間: {
   値: 0
  },
  速度:
   値: this.params.velocity
  },
  uテクスチャ: {
   値: this.rt.texture
  },
  uシャドウ:
   値: this.params.shadow
  },
  u頻度: {
   値: this.params.frequency
  }
  }
 });
 this.material = マテリアル;
 const メッシュ = this.createMesh({
  幾何学、
  材料
 });
 this.mesh = メッシュ;
 }
 アップデート() {
 if (this.rtScene) {
  this.renderer.setRenderTarget(this.rt);
  this.renderer.render(this.rtScene、this.rtCamera);
  this.renderer.setRenderTarget(null);
 }
 経過時間を取得します。
 if (this.material) {
  this.material.uniforms.uTime.value = 経過時間;
 }
 }
}

カメラを遠くに動かすのを忘れないでください

this.cameraPosition = 新しい THREE.Vector3(0, 0, 40);

セクシーなダイナミックテキストが表示されます :)

プロジェクトギャラリー

キネティックテキスト

デモには、この記事で作成したものよりも多くの図形があります。自由に試してみてください。

要約する

three.js で 3D ダイナミック テキスト効果を実現する方法についての記事はこれで終わりです。three.js 3D ダイナミック テキストの関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Three.js が Facebook Metaverse 3D ダイナミック ロゴ効果を実現
  • three.js を使って立体的な矢印線を描く詳細な手順
  • three.js を使用してクールなアシッドスタイルの 3D ページ効果を実現します
  • 露滴アニメーション効果を実装するための Three.js サンプル コード
  • three.js でのマルチスレッドの使用とパフォーマンステストの詳細な説明
  • JavaScript Three.js でテキストを作成する最初の経験

<<:  Linux での MySQL 5.6.33 のインストールと設定のチュートリアル

>>:  Linux での SSH 非秘密通信の実装

推薦する

PostgreSQL正規表現の一般的な機能の概要

PostgreSQL正規表現の一般的な機能の概要正規表現は、複雑なデータ処理を必要とするプログラムに...

Raspberry PiにDockerをインストールする方法

Raspberry Pi は ARM アーキテクチャをベースとしているため、Docker のインスト...

Vue での weixin-js-sdk の一般的な使用方法の詳細な説明

リンク: https://qydev.weixin.qq.com/wiki/index.php?ti...

Linux で crontab 出力リダイレクトが有効にならない問題の解決方法

質問LINUX では、定期的なタスクは通常、cron デーモン プロセス [ps -ef | gre...

React Fragment の紹介と詳しい使い方

目次序文フラグメントの動機React Fragment の紹介と使用<React.Fragme...

CD コマンドを使わずに Linux でディレクトリ/フォルダに入る方法

ご存知のとおり、cd コマンドがないと、Linux でディレクトリを切り替えることはできません。それ...

MySQL 5.6.22 のインストールと設定方法のグラフィックチュートリアル

このチュートリアルでは、MySQL5.6.22のインストールと設定方法の具体的なコードを参考までに共...

Vue パッケージアップロードサーバー更新 404 問題に対する 2 つの解決策

1: nginxサーバーソリューション、.conf構成ファイルを変更する解決策は2つある1: 位置 ...

JavaScript イベント委任 (プロキシ) の使用例の詳細

目次導入例: イベントの委任記述方法1: イベント委譲書き方2: 各子要素がイベントをバインドする例...

詳細なハードウェア情報を取得するための Linux のいくつかのコマンドの詳細な説明

Linux システム、特にサーバー システムでは、デバイスのハードウェア情報を表示する必要がよくあり...

ソースコードから、Vue2がデータとメソッドを直接取得できる理由がわかる

目次1. 例: これはデータとメソッドを直接取得できます2. 環境を準備し、ソースコードをデバッグし...

Dockerで最もよく使われるイメージコマンドとコンテナコマンドの詳細な説明

この記事では、Docker の使用で最もよく使用されるイメージ コマンドとコンテナ コマンドを一覧表...

VUEは登録とログインの効果を実現します

この記事の例では、登録とログインの効果を実現するためのVUEの具体的なコードを紹介します。具体的な内...

値の転送を実現するために、2つの同じレベルのコンポーネントをVueで作成します。

Vue コンポーネントは接続されているため、コンポーネント間で値を渡す必要があるのは避けられません...

Vue の foreach 配列と js の traversal 配列の書き方の説明

Vue foreach配列を記述し、jsで配列をトラバースする方法シナリオVueでAxiosを使用し...