Transitions de shader

Starter pack

Dans cette leçon, nous allons apprendre à créer des transitions en utilisant des shaders.

Le premier effet que nous allons créer est un effet de transition d'écran :

Nous avons un contrôle total sur l'effet de transition, nous pouvons changer la durée, la fonction d'animation, et le shader lui-même.

Le deuxième effet que nous allons créer est un effet de transition de modèle :

Lors de la disparition, le modèle est dissous et les couleurs sont lavées en blanc, l'inverse se produit lors de l'apparition.

Pack de démarrage

Voici tous les modèles 3D que nous utiliserons dans cette leçon par Ergoni et sous licence Creative Commons Attribution:

Le pack de démarrage utilise les packages suivants :

Les deux polices utilisées sont Kanit et Rubik Doodle Shadow, toutes deux issues de Google Fonts.

N'hésitez pas à ajuster les composants selon vos préférences.

Vous pouvez ajuster les couleurs en jouant avec les contrôles de Leva dans le coin supérieur droit. Une fois que vous avez trouvé les couleurs qui vous plaisent, ajoutez la prop hidden au composant Leva dans App.jsx :

// ...

function App() {
  // ...
  return (
    <>
      <Leva hidden />
      {/* ... */}
    </>
  );
}

// ...

Transition d'écran

Commençons par créer notre effet de transition d'écran. Nous allons créer un composant appelé ScreenTransition qui gérera l'effet de transition.

Créons un nouveau fichier appelé ScreenTransition.jsx dans le dossier components:

export const ScreenTransition = ({ transition, color }) => {
  return (
    <mesh>
      <planeGeometry args={[2, 2]} />
      <meshBasicMaterial color={color} />
    </mesh>
  );
};

Dans ce composant, nous créons un plan avec une couleur qui couvrira l'écran entier. Nous utiliserons ce plan pour la transition entre les écrans.

Notre composant prend deux props :

  • transition : un booléen pour savoir si le composant doit afficher l'effet de transition
  • color : la couleur principale de l'effet de transition

Ajoutons le composant ScreenTransition à App.jsx:

// ...
import { ScreenTransition } from "./components/ScreenTransition";

function App() {
  // ...
  return (
    <>
      {/* ... */}
      <Canvas camera={{ position: [0, 1.8, 5], fov: 42 }}>
        <color attach="background" args={[backgroundColor]} />
        <fog attach="fog" args={[backgroundColor, 5, 12]} />
        <ScreenTransition transition color="#a5b4fc" />
        <Suspense>
          <Experience />
        </Suspense>
      </Canvas>
    </>
  );
}

export default App;

Pour le moment, nous forçons l'affichage de l'effet de transition en passant true à la prop transition. Nous ajouterons la logique pour contrôler l'effet de transition plus tard.

Ajustez la couleur à votre goût. Si vous la changez, assurez-vous de mettre à jour la couleur dans le fichier index.css pour éviter un flash de couleur lors du chargement du site Web:

// ...

html {
  background-color: #a5b4fc;
}

Plane in middle of the scene

Le plan est au milieu de la scène.

Plan plein écran

Nous voulons que notre plan couvre l'ensemble de l'écran. Nous pourrions utiliser les dimensions du viewport et le faire face à la caméra, mais nous voulons également qu'il soit au-dessus de tout.

Pour y parvenir, Drei fournit un composant Hud qui rendra ses enfants par-dessus tout. Nous pouvons ajouter une caméra fixe au composant Hud pour être sûr qu'elle est parfaitement alignée avec notre plan :

import { Hud, OrthographicCamera } from "@react-three/drei";

export const ScreenTransition = ({ transition, color }) => {
  return (
    <Hud>
      <OrthographicCamera
        makeDefault
        top={1}
        right={1}
        bottom={-1}
        left={-1}
        near={0}
        far={1}
      />
      <mesh>
        <planeGeometry args={[2, 2]} />
        <meshBasicMaterial color={color} />
      </mesh>
    </Hud>
  );
};

Nous utilisons une OrthographicCamera pour facilement couvrir l'ensemble de l'écran, quelle que soit la distance entre la caméra et le plan.

Plane covering the entire screen

Le plan couvre maintenant l'ensemble de l'écran.

Logique de transition

Une dernière chose avant de créer notre shader personnalisé, définissons un état de transition dans UI.jsx :

// ...
import { atom } from "jotai";

export const transitionAtom = atom(true);
// ...

Nous définissons la valeur initiale à true pour commencer avec un effet de fondu après le chargement du site.

Nous utiliserons cet état pour contrôler l'effet de transition.

Toujours dans UI.jsx, nous allons définir deux constantes pour contrôler la durée et le délai de l'effet de transition :

// ...
export const TRANSITION_DELAY = 0.8;
export const TRANSITION_DURATION = 3.2;
// ...

Maintenant, remplaçons l'appel de la fonction setScreen par une nouvelle qui gérera l'effet de transition :

// ...
import { useAtom } from "jotai";
import { useRef } from "react";
// ...

export const UI = () => {
  // ...
  const [transition, setTransition] = useAtom(transitionAtom);
  const timeout = useRef();

  // ...
  const transitionToScreen = (newScreen) => {
    setTransition(true);
    clearTimeout(timeout.current);
    timeout.current = setTimeout(() => {
      setScreen(newScreen);
      setTransition(false);
    }, TRANSITION_DURATION * 1000 + TRANSITION_DELAY * 1000);
  };
  // ...
};

Au lieu de définir directement le nouvel écran, nous définissons l'état de transition sur true et utilisons un setTimeout pour définir le nouvel écran après la fin de l'effet de transition (la durée de l'effet de transition plus le délai).

Maintenant notre fonction est prête, cherchez les appels setScreen dans le composant UI et remplacez-les par transitionToScreen.

De home à menu :

<motion.button
  onClick={() => transitionToScreen("menu")}
  // ...
>

Et de menu à home :

<motion.button
onClick={() => transitionToScreen("home")}
// ...
>

End of lesson preview

To get access to the entire lesson, you need to purchase the course.