序文みなさんこんにちは。CSS ウィザードの alphardex です。 以前、海外のウェブサイトを閲覧していたとき、いくつかのウェブサイトのテキストが 3D グラフィックに刻まれていて、グラフィック上を動かせることに気づきました。視覚効果がかなり良かったので、私も three.js を使ってこの効果を再現したいと思いました。 上の写真はエフェクトの 1 つにすぎません。それでは始めましょう。 準備私が自分でパッケージ化した three.js テンプレート: Three.js Starter 読者は、このプロジェクトを始める前に右下隅をクリックしてコピーをフォークすることができます。 このプロジェクトにはビットマップ フォントが必要です。デモの HTML でフォント コードを直接コピーできます。 注意: three-bmfont-text ライブラリはグローバルの three.js に依存しているため、以下に示すように、JS で three.js をもう一度インポートする必要があります。 実装のアイデア
ポジティブ足場を設置する <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 をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Linux での MySQL 5.6.33 のインストールと設定のチュートリアル
Webサービスのリモートデバッグ.NET では、WEBSERVICE のリモート デバッグ機能はデフ...
mysql バッチで大量のデータを削除する1000万件のレコードを持つテーブル(syslogs)があ...
DockerデーモンソケットDocker デーモンは、 unix 、 tcp 、 fdの 3 種類の...
Iframe Web ページのナビゲーション ウィンドウに関する簡単な説明 Iframe ウェブペー...
この記事では、thinkphp5.1 + Vue+axiosを使用してファイルをアップロードする方法...
操作効果 html <ヘッド> <メタ文字セット='UTF-8'&...
1. プロジェクトの実行時に報告されるエラー情報は次のとおりです。 ファイル "/home...
目次ロックの概要ロックの分類データベース操作の粒度データ操作の種類MySQL ロックさまざまなストレ...
目次1. はじめに2. 行き詰まった問題の分析3. 解決策(理論) 4. ソリューション(コード) ...
こんなことがありました。今日はGitHubで遊んでいました。最初はログインせずにいくつかのページを閲...
1. 目的Flask アプリケーションをローカルで作成し、Docker でパッケージ化し、独自のサー...
プロジェクト要件では、アップロードされたドキュメントの前処理が必要です。ユーザーが doc 形式でド...
1. 基礎知識(日付オブジェクトのメソッド) 😜 getFullYear() は年を表す4桁の数字を...
Zabbix バージョン 3.0 以降、Zabbix サーバー、Zabbix プロキシ、Zabbi...
序文ご存知のとおり、「CSS で要素を垂直方向に中央揃えするにはどうすればよいか」という質問は、すで...