Fundamentals
Core
Master
Shaders
3Dポートフォリオ
インターフェース
3Dシーンがほぼ完成したので、HTMLインターフェースの作業を開始できます。
3Dシーンと同じ4つのセクションを持つInterface.jsx
コンポーネントを作成しましょう:
export const Interface = () => { return ( <div className="interface"> <div className="sections"> {/* HOME */} <section className="section section--bottom">HOME</section> {/* SKILLS */} <section className="section section--right">SKILLS</section> {/* PROJECTS */} <section className="section section--left">PROJECTS</section> {/* CONTACT */} <section className="section section--left">CONTACT</section> </div> </div> ); };
section--bottom
、section--right
、およびsection--left
クラスを使って、セクション内のコンテンツを配置します。
現時点ではセクション名のみを追加しました。コンテンツは後で追加します。
Interface
コンポーネントをApp
コンポーネントに追加しましょう:
import { Scroll, ScrollControls } from "@react-three/drei"; import { Canvas } from "@react-three/fiber"; import { MotionConfig } from "framer-motion"; import { Experience } from "./components/Experience"; import { config } from "./config"; import { Interface } from "./components/Interface"; function App() { return ( <> <Canvas camera={{ position: [0, 0.5, 5], fov: 42 }}> <color attach="background" args={["#f5f3ee"]} /> <fog attach="fog" args={["#f5f3ee", 10, 50]} /> <ScrollControls pages={config.sections.length} damping={0.1} maxSpeed={0.2} > <group position-y={-1}> <MotionConfig transition={{ duration: 0.6, }} > <Experience /> </MotionConfig> </group> <Scroll html> <Interface /> </Scroll> </ScrollControls> </Canvas> </> ); } export default App;
HTMLインターフェースをスタイルするために、可能な限り汎用的なvanilla CSSを使用します。お好きなCSSフレームワークを使用しても構いません。 (私はほとんどのプロジェクトでTailwindCSSを使用しています)
index.css
ファイルにデフォルトのスタイルを追加しましょう:
@import url("https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;700&display=swap"); :root { --primary-color: #4668ee; --text-color: #1a202c; --text-light-color: #555; } #root { width: 100vw; height: 100vh; } body { margin: 0; font-family: "Roboto Slab", serif; } /* ... */ .interface { width: 100vw; display: flex; flex-direction: column; align-items: center; } .sections { max-width: 1200px; width: 100%; } .section { height: 100vh; display: flex; justify-content: center; align-items: center; } .section--top { align-items: flex-start; } .section--bottom { align-items: flex-end; } .section--right { justify-content: flex-end; } .section--left { justify-content: flex-start; }
Google FontsからRoboto Slabフォントをインポートし、いくつかのカラー変数を定義しました。
セクションコンテナは中央に配置されており、大画面での可読性を保つためにmax-width
が1200px
に設定されています。
セクションのheight
は100vh
(全高) でデフォルトでは中央に配置されています。section--top
、section--bottom
、section--right
、およびsection--left
クラスを使用してセクション内のコンテンツを配置します。
インターフェースは準備完了です。次にコンテンツを追加しましょう!
ホームスクロールインジケーター
ホームセクションでは、ユーザーがスクロールできることを知らせるためにスクロールインジケーターを追加します。
最初に、ユーザーがスクロールしたかどうかを知るための状態を作成しましょう:
import { useScroll } from "@react-three/drei"; import { useFrame } from "@react-three/fiber"; import { useState } from "react"; export const Interface = () => { const scrollData = useScroll(); const [hasScrolled, setHasScrolled] = useState(false); useFrame(() => { setHasScrolled(scrollData.offset > 0); }); // ... };
次に、ホームセクションにmotion.div
とvariants
オブジェクトを追加して、アニメーションスクロールインジケーターを作成します:
// ... import { motion } from "framer-motion"; export const Interface = () => { // ... return ( <div className="interface"> <div className="sections"> {/* HOME */} <section className="section section--bottom"> <motion.div className="scroll-down" initial={{ opacity: 0, }} animate={{ opacity: hasScrolled ? 0 : 1, }} > <motion.div className="scroll-down__wheel" initial={{ translateY: 0, }} animate={{ translateY: 4, }} transition={{ duration: 0.4, repeatDelay: 0.5, repeatType: "reverse", repeat: Infinity, }} ></motion.div> </motion.div> </section> {/* ... */} </div> </div> ); };
framer motionを使用して、opacityとwheelの位置をアニメーションします。wheelを上下に動かすために、repeat
とrepeatType
プロパティを使用します。
End of lesson preview
To get access to the entire lesson, you need to purchase the course.