Portfolio 3D

Starter pack

Interfaccia

Ora che la nostra scena 3D è principalmente completa, possiamo iniziare a lavorare sull'interfaccia HTML.

Creiamo un componente Interface.jsx con le stesse 4 sezioni della nostra scena 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>
  );
};

Utilizzeremo le classi section--bottom, section--right e section--left per posizionare il contenuto all'interno delle sezioni.

Per il momento abbiamo solo aggiunto i nomi delle sezioni, aggiungeremo il contenuto in seguito.

Aggiungiamo il nostro componente Interface nel componente 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;

Per stilizzare la nostra interfaccia HTML, useremo vanilla CSS per essere il più generici possibile. Puoi utilizzare il tuo framework CSS preferito se lo desideri. (Ho utilizzato TailwindCSS in molti dei miei progetti)

Aggiungiamo gli stili di default al nostro file 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;
}

Abbiamo importato il font Roboto Slab da Google Fonts e definito alcune variabili di colore.

Il contenitore delle sezioni è centrato e ha un max-width di 1200px per mantenere una buona leggibilità su schermi grandi.

Le sezioni hanno un height di 100vh (altezza completa) e sono centrate di default. Utilizzeremo le classi section--top, section--bottom, section--right e section--left per posizionare il contenuto all'interno delle sezioni.

La nostra interfaccia è pronta, aggiungiamo il contenuto!

Indicatore di scorrimento nella home

Nella sezione iniziale, aggiungeremo un indicatore di scorrimento per informare l'utente che può scorrere per vedere le altre sezioni.

Per prima cosa, creiamo uno stato per sapere se l'utente ha effettuato uno scroll:

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);
  });
  // ...
};

Poi, nella sezione home, possiamo aggiungere un motion.div con un oggetto variants per creare un indicatore di scorrimento animato:

// ...
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>
  );
};

Utilizziamo framer motion per animare l'opacità e la posizione della ruota. Per far muovere la ruota su e giù, usiamo le proprietà repeat e repeatType.

Three.js logoReact logo

React Three Fiber: The Ultimate Guide to 3D Web Development

✨ You have reached the end of the preview ✨

Go to the next level with Three.js and React Three Fiber!

Get full access to this lesson and the complete course when you enroll:

  • 🔓 Full lesson videos with no limits
  • 💻 Access to the final source code
  • 🎓 Course progress tracking & completion
  • 💬 Invite to our private Discord community
Unlock the Full Course – Just $85

One-time payment. Lifetime updates included.