昨年、私はトイレルのプロジェクトでショーン・ワン(Swyx)と協力する機会がありました。目標は、いくつかの創造的な要素でウェブサイトを強化することでした。私はデザイナーというよりも開発者の方が魅力的な課題でしたが、デザインスキルを拡大する機会を受け入れました。
私の貢献の1つは、インタラクティブな星空の背景でした。ここで動作しているのを見ることができます:
パースペクティブとCSSカスタムプロパティを使用したBlockQuoteコンセプト。 @temporalioで創造的な自由を楽しんでいます。気まぐれなタッチを追加! ⚒️@ReACTJS && @TailWindCSS(サイトIS NextJS)? @codepen pic.twitter.com/s9xp2trroxを介してCodepenにリンクします
- jhey ??✨(@jh3yy)2021年7月2日
このデザインの強度は、再利用可能な反応成分としての実装にあり、高い構成可能性を提供します。星の代わりに異なる形状が必要ですか?粒子の配置を正確に制御したいですか?あなたは完全に制御されています。
このコンポーネントを構築しましょう! React、Greensock、およびHTMLを使用します<canvas></canvas>
要素。 Reactはオプションですが、それを使用すると、将来のプロジェクトに再利用可能なコンポーネントが作成されます。
'https://cdn.skypack.dev/react'からのインポートReact; 'https://cdn.skypack.dev/react-dom'からReactdomをインポートします。 'https://cdn.skypack.dev/gsap'からGSAPをインポートします。 const root_node = document.queryselector( '#app'); const starscape =()=><h1>かっこいい!</h1> ; const app =()=><starscape></starscape> ; Reactdom.Render(<app></app> 、root_node);
まず、aをレンダリングします<canvas></canvas>
要素とReactのuseEffect
フック内で使用するための参照をつかみます。 Reactを使用していない場合は、参照を変数に直接保存します。
const starscape =()=> { const canvasref = race.useref(null); 戻る<canvas ref="{canvasRef}"></canvas>; };
スタイリングします<canvas></canvas>
ビューポートを埋めてコンテンツの後ろに座るには:
キャンバス{ 位置:修正; 挿入図:0; 背景:#262626; z -index:-1; 高さ:100VH; 幅:100VW; }
不透明度やサイズがさまざまなサークルを使用して、スターレンダリングを簡素化します。 aに円を描きます<canvas></canvas>
コンテキストを取得し、 arc
関数を使用することを伴います。 useEffect
フックを使用して、中央に円(私たちの星)をレンダリングしましょう。
const starscape =()=> { const canvasref = race.useref(null); const contextref = React.useref(null); React.useeffect(()=> { canvasref.current.width = window.innerwidth; canvasref.current.height = window.innerheight; contextref.current = canvasref.current.getContext( '2d'); contextref.current.fillstyle = 'Yellow'; contextref.current.beginPath(); contextref.current.arc( window.innerwidth / 2、// x window.innerheight / 2、// y 100、//半径 0、//角度を開始(ラジアン) Math.Pi * 2 //終了角度(ラジアン) ); contextref.current.fill(); }、[]); 戻る<canvas ref="{canvasRef}"></canvas>; };
これにより、黄色の円が作成されます。残りのコードは、このuseEffect
内にあります。これが、反応部分がオプションである理由です。このコードを他のフレームワークに適応させることができます。
複数の星を生成してレンダリングする必要があります。キャンバスのサイジングを含む星生成とキャンバスのセットアップを処理するためのLOAD
関数を作成しましょう。
const load =()=> { const vmin = math.min(window.innerheight、window.innerwidth); const star_count = math.floor(vmin * densityratio); canvasref.current.width = window.innerwidth; canvasref.current.height = window.innerheight; Starsref.current = new Array(star_count).fill()。map(()=>({{ X:gsap.utils.random(0、window.innerwidth、1)、 y:gsap.utils.random(0、window.innerheight、1)、 サイズ:gsap.utils.random(1、sizelimit、1)、 スケール:1、 アルファ:gsap.utils.random(0.1、defaultalpha、0.1)、 })); };
各星は、その特性(x、y位置、サイズ、スケール、アルファ)を定義するプロパティを持つオブジェクトです。 sizeLimit
、 defaultAlpha
、およびdensityRatio
、デフォルト値を持つStarscape
コンポーネントに渡されたプロップです。
サンプルスターオブジェクト:
{ 「X」:1252、 「Y」:29、 「サイズ」:4、 「スケール」:1、 「アルファ」:0.5 }
これらの星をレンダリングするために、 arc
関数を使用してstars
を繰り返し、各星をレンダリングするRENDER
関数を作成します。
const render =()=> { contextref.current.clearrect( 0、 0、 canvasref.current.width、 canvasref.current.height ); starsref.current.foreach((star)=> { contextref.current.fillstyle = `hsla(0、100%、100%、$ {star.alpha})`; contextref.current.beginPath(); contextref.current.arc(star.x、star.y、star.size / 2、0、math.pi * 2); contextref.current.fill(); }); };
clearRect
関数は、レンダリングの前にキャンバスをクリアします。これはアニメーションに重要です。
完全なStarscape
コンポーネント(まだ対話性なし)を以下に示します。
完全なスタースケープコンポーネント(対話性なし)
const starscape =({denthesratio = 0.5、sizelimit = 5、defaultalpha = 0.5})=> { const canvasref = race.useref(null); const contextref = React.useref(null); const starsref = race.useref(null); React.useeffect(()=> { contextref.current = canvasref.current.getContext( '2d'); const load =()=> { const vmin = math.min(window.innerheight、window.innerwidth); const star_count = math.floor(vmin * densityratio); canvasref.current.width = window.innerwidth; canvasref.current.height = window.innerheight; Starsref.current = new Array(star_count).fill()。map(()=>({{ X:gsap.utils.random(0、window.innerwidth、1)、 y:gsap.utils.random(0、window.innerheight、1)、 サイズ:gsap.utils.random(1、sizelimit、1)、 スケール:1、 アルファ:gsap.utils.random(0.1、defaultalpha、0.1)、 })); }; const render =()=> { contextref.current.clearrect(0、0、canvasref.current.width、canvasref.current.height); starsref.current.foreach((star)=> { contextref.current.fillstyle = `hsla(0、100%、100%、$ {star.alpha})`; contextref.current.beginPath(); contextref.current.arc(star.x、star.y、star.size / 2、0、math.pi * 2); contextref.current.fill(); }); }; const run =()=> { 負荷(); 与える(); }; 走る(); window.addeventlistener( 'resize'、run); return()=> { window.removeeventlistener( 'resize'、run); }; }、[]); 戻る<canvas ref="{canvasRef}"></canvas>; };
デモで小道具を試して、それらの効果を確認します。ビューポートのサイズ変更を処理するために、 LOAD
を呼び出してサイズRENDER
(最適化のために脱出します。これはここで簡潔に省略されています)。
それでは、背景をインタラクティブにしましょう。ポインターが動くと、カーソルの近くの星が明るくなり、スケールアップします。
UPDATE
関数を追加して、ポインターと各星間の距離を計算し、GreensockのmapRange
ユーティリティを使用してStarのスケールとアルファをトゥイーンします。また、スケーリングの動作を制御するために、 scaleLimit
およびproximityRatio
小道具を追加します。
const update =({x、y})=> { starsref.current.foreach((star)=> { const distance = math.sqrt(math.pow(star.x -x、2)math.pow(star.y -y、2)); gsap.to(star、{ スケール:scalemapperref.current(math.min(distance、vminref.current * proximityratio))、 alpha:alphamapperref.current(math.min(distance、vminref.current * proximityratio))、 }); }); };
更新をレンダリングするには、 gsap.ticker
( requestAnimationFrame
の優れた代替手段)を使用して、ティッカーにRENDER
を追加してクリーンアップで削除します。 1秒あたりのフレーム(FPS)を24に設定します。 RENDER
関数は、ARCを描画するときにstar.scale
値を使用するようになりました。
負荷(); gsap.ticker.add(render); gsap.ticker.fps(24); window.addeventlistener( 'resize'、load); document.addeventlistener( 'pointermove'、update); return()=> { window.removeeventlistener( 'resize'、load); document.removeeventlistener( 'pointermove'、update); gsap.ticker.remove(render); };
さて、マウスを動かすと、星は反応します!
マウスがキャンバスを離れるケースを処理するために、星を元の状態に戻すpointerleave
イベントリスナーを追加します。
const exit =()=> { gsap.to(starsref.current、{scale:1、alpha:defaultalpha}); }; // ...イベントリスナー... document.addeventlistener( 'pointerleave'、exit); return()=> { // ... 掃除 ... document.removeeventlistener( 'pointerleave'、exit); gsap.ticker.remove(render); };
コナミコードのイースターエッグを追加しましょう。キーボードイベントを聴き、コードが入力されている場合はアニメーションをトリガーします。
const konami_code = 'arrowup、arrowup、arrowdown、arrowdown、arrowleft、arrowright、arrowleft、arrowright、keyb、keya'; const coderef = React.useref([]); React.useeffect(()=> { const handlecode =(e)=> { coderef.current = [... coderef.current、e.code] .slice(coderef.current.length> 9?coderent.length.length -9:0); if(coderef.current.join( '、')。tolowercase()=== konami_code.tolowercase()){ //イースターエッグアニメーションをトリガーします } }; window.addeventlistener( 'keyup'、handlecode); return()=> { window.removeeventlistener( 'keyup'、handlecode); }; }、[]);
コナミコードのイースターエッグを使用した完全でインタラクティブなStarscape
コンポーネントは非常に長く、ここでは簡潔に省略されています。ただし、上記の原則は、React、Greensock、およびHTMLを使用して、完全に機能的でカスタマイズ可能なインタラクティブな星空の背景を作成する方法を示しています<canvas></canvas>
。イースターエッグアニメーションには、 gsap.timeline
作成して星のプロパティをアニメーション化することが含まれます。
この例は、独自のカスタム背景を作成するために必要な手法を示しています。背景がサイトのコンテンツとどのように相互作用するかを忘れないでください。さまざまな形、色、アニメーションを試して、ユニークで魅力的なビジュアルを作成します。
以上がコンテンツ用のインタラクティブな星空の背景の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。