Fundamentals
Core
Master
Shaders
Portfolio 3D
Interface
Maintenant que notre scène 3D est principalement terminée, nous pouvons commencer à travailler sur l'interface HTML.
Créons un composant Interface.jsx
avec les 4 mêmes sections que notre scène 3D :
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> ); };
Nous utiliserons les classes section--bottom
, section--right
et section--left
pour positionner le contenu à l'intérieur des sections.
Pour le moment, nous avons seulement ajouté les noms des sections, nous ajouterons le contenu plus tard.
Ajoutons notre composant Interface
dans le composant 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;
Pour styliser notre interface HTML, nous utiliserons le CSS vanilla pour être le plus générique possible. Vous pouvez utiliser votre framework CSS préféré si vous le souhaitez. (J'ai utilisé TailwindCSS sur la plupart de mes projets)
Ajoutons les styles de base Ă notre fichier 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; }
Nous avons importé la police Roboto Slab de Google Fonts et défini quelques variables de couleurs.
Le conteneur des sections est centré et a une max-width
de 1200px
pour maintenir une bonne lisibilité sur les grands écrans.
Les sections ont une height
de 100vh
(hauteur complète) et sont centrées par défaut. Nous utiliserons les classes section--top
, section--bottom
, section--right
et section--left
pour positionner le contenu à l'intérieur des sections.
Notre interface est prĂŞte, ajoutons le contenu !
Indicateur de défilement d'accueil
Sur la section d'accueil, nous allons ajouter un indicateur de défilement pour informer l'utilisateur qu'il peut faire défiler pour voir les autres sections.
Tout d'abord, créons un état pour savoir si l'utilisateur a fait défiler :
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); }); // ... };
Ensuite, dans la section d'accueil, nous pouvons ajouter un motion.div
avec un objet variants
pour créer un indicateur de défilement animé :
// ... import { motion } from "framer-motion"; export const Interface = () => { // ... return ( <div className="interface"> <div className="sections"> {/* ACCUEIL */} <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> ); };
Nous utilisons framer motion pour animer l'opacité et la position de la roue. Pour faire bouger la roue de haut en bas, nous utilisons les propriétés repeat
et repeatType
.
End of lesson preview
To get access to the entire lesson, you need to purchase the course.