Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 44

Communication 3D-2D : Scène et Interface Utilisateur (HTML/CSS)

Recommended resources

Bonjour ! Bienvenue dans cette nouvelle leçon.

Dans la leçon précédente, nous avons découvert comment utiliser Leva pour créer un panneau de contrôle qui modifie notre scène 3D en temps réel. C'était notre première incursion dans la communication entre une interface 2D et notre monde 3D. Cependant, Leva est avant tout un outil de développement. Pour une application professionnelle, nous devons construire notre propre interface utilisateur avec HTML, CSS et React.

L'objectif de cette leçon est donc de maîtriser une compétence fondamentale : faire communiquer la scène 3D avec l'interface utilisateur 2D (HTML/CSS). Nous verrons comment une action sur un bouton HTML peut changer la couleur d'un objet 3D, et inversement, comment une interaction dans la scène 3D pourrait, à terme, mettre à jour notre UI. C'est le secret derrière les configurateurs de produits, les portfolios interactifs et bien d'autres expériences web modernes.

3D Scene with Integrated 2D UI for Interaction
Cette image illustre parfaitement notre objectif : des boutons HTML standards superposés à une scène 3D, prêts à déclencher des événements.

1. Le Principe Fondamental : L'État Partagé

La clé pour faire communiquer le monde 2D (vos composants React classiques) et le monde 3D (vos composants à l'intérieur du <Canvas>) est simple : ils doivent partager un état React.

Puisque les deux "mondes" sont des composants React, ils peuvent tous deux lire et mettre à jour le même état. Quand l'interface 2D met à jour l'état, le composant 3D qui lit cet état se re-rendra avec les nouvelles valeurs, et vice-versa.

Il existe deux patrons d'architecture principaux pour y parvenir :

  1. Le "State Lift-up" (Remontée d'état) : L'état est géré dans le composant parent le plus proche qui englobe à la fois l'UI 2D et la scène 3D. L'état et les fonctions pour le modifier sont ensuite passés en props.
  2. Le "React Context" : L'état est placé dans un fournisseur de contexte qui englobe toute l'application. N'importe quel composant, qu'il soit en 2D ou en 3D, peut alors "consommer" cet état sans avoir besoin de le recevoir via les props.

Commençons par le plus simple.


2. Patron n°1 : La Remontée d'État (State Lift-up)

Cette approche est idéale pour des interactions simples. L'idée est de déclarer votre useState dans un composant qui contient à la fois votre UI HTML et votre <Canvas>.

Cet article, bien que simple, illustre parfaitement ce concept.

React Three Fiber: Rendering 3D in React Made Simple - Medium

Cet article montre l'exemple le plus simple de communication 2D -> 3D. Nous allons nous concentrer sur la manière dont un bouton HTML contrôle la rotation des cubes.

Lisez la section sous le titre "Creating Scene and Objects". Concentrez-vous sur le dernier bloc de code (pages/index.tsx). Repérez où l'état rotate est déclaré avec useState, comment le bouton <button> utilise setRotate, et comment la valeur rotate est passée en prop aux composants <Box /> à l'intérieur du <Canvas>.

Analysons la structure du code que vous venez de voir :

// Fichier `App.js` ou un composant parent
import { useState } from "react";
import { Canvas } from "@react-three/fiber";
import Box from "./Box";

export default function App() {
  // 1. L'état est déclaré dans le parent commun.
  const [isRotating, setIsRotating] = useState(true);

  return (
    <>
      {/* 2. L'UI 2D (un simple bouton) modifie l'état. */}
      <button onClick={() => setIsRotating(!isRotating)}>
        {isRotating ? "Stop" : "Start"} Rotation
      </button>

      {/* 3. Le composant Canvas contient la scène 3D */}
      <Canvas>
        {/* 4. La valeur de l'état est passée en prop au composant 3D. */}
        <Box rotate={isRotating} position={[-1.2, 0, 0]} />
        <Box rotate={isRotating} position={[1.2, 0, 0]} />
      </Canvas>
    </>
  );
}

Dans le composant Box, le hook useFrame utiliserait cette prop rotate pour décider d'appliquer ou non la rotation à chaque frame. C'est simple, direct et très efficace pour des besoins ciblés.


3. Patron n°2 : Le React Context (La Solution Évolutive)

Lorsque votre application grandit, passer des props à travers de multiples couches de composants (ce qu'on appelle le "prop drilling") devient fastidieux. C'est là que le React Context brille. Il agit comme un "magasin" d'état global accessible de n'importe où.

C'est le patron de choix pour des applications complexes comme un configurateur de produit, où de nombreux composants 2D (choix de couleurs, de textures, d'options) doivent affecter de nombreuses parties du modèle 3D.

La vidéo suivante est un excellent tutoriel qui construit un configurateur de chaise de A à Z en utilisant ce patron.

React Three Fiber tutorial - 3D Product Configurator

Cette vidéo de Wawa Sensei est un cas d'étude parfait. Nous allons la découper en trois parties pour bien comprendre la mise en place du patron Context.

Pour commencer, regardez comment l'interface 2D est simplement créée en HTML/CSS et placée à côté du Canvas (de 00:25:39 à 00:32:22). À ce stade, elle ne fait encore rien, c'est juste une structure visuelle.

Maintenant que l'UI est en place, créons le système qui la rendra vivante.

Étape 1 : Créer le Contexte

Le "cerveau" de notre système sera un contexte React. C'est un composant qui va contenir tous nos états (useState) et les rendre disponibles à tous ses enfants.

React Three Fiber tutorial - 3D Product Configurator

Regardons maintenant la partie la plus importante : la création du Contexte. C'est ici que nous centralisons l'état de notre application.

Regardez de 00:32:22 à 00:36:27. Concentrez-vous sur la création du fichier CustomizationContext.jsx. Observez : L'utilisation de createContext pour initialiser le contexte. La création du CustomizationProvider qui contient les useState (pour material ici). La création du hook useCustomization pour permettre aux composants d'accéder facilement au contexte.

Étape 2 : Connecter l'UI 2D et la Scène 3D

Une fois le Provider enroulé autour de notre application, l'UI 2D peut utiliser le hook useCustomization pour modifier l'état, et la scène 3D peut l'utiliser pour lire cet état et se mettre à jour. C'est la magie du Context.

React Three Fiber tutorial - 3D Product Configurator

Maintenant, connectons les deux mondes. C'est le moment où tout prend sens.

Regardez la vidéo de 00:36:27 à 00:40:19. C'est une section dense mais cruciale. Notez comment : Le composant UI Configurator.jsx récupère setMaterial et setLegs depuis useCustomization pour les lier aux événements onClick des boutons. Le composant 3D Chair.jsx récupère material et legs depuis le même hook useCustomization pour changer conditionnellement les textures ou la visibilité des objets.

Ce patron est extrêmement puissant et constitue la base de la plupart des applications R3F professionnelles.


4. Communication par le Défilement (Scrolling)

Une autre forme de communication très populaire consiste à lier le défilement (scroll) d'une page HTML à des animations dans la scène 3D. L'utilisateur fait défiler une page de présentation, et en arrière-plan, la caméra bouge, des objets apparaissent, etc.

La librairie drei facilite cela avec le composant ScrollControls.

La vidéo ci-dessous montre comment une action sur l'UI 2D (ouvrir un menu) peut directement influencer la caméra 3D. Cela renforce notre principe d'état partagé.

Build a 3D Portfolio with React Three Fiber - Framer Motion Scroll Animations

Pour finir, voyons un exemple plus avancé. Cette vidéo montre comment l'état d'un menu 2D contrôle la caméra 3D, créant une expérience utilisateur très fluide.

Regardez de 00:41:01 à 00:44:50. Observez comment la prop menuOpened (un simple booléen provenant de l'état de l'UI 2D) est passée au composant 3D Experience. À l'intérieur, un useEffect ou useFrame réagit à ce changement d'état pour animer la position de la caméra.

C'est une excellente démonstration de la façon dont un état simple, géré au niveau de l'UI, peut avoir un impact direct et sophistiqué sur le monde 3D.


Conclusion

Aujourd'hui, vous avez appris la compétence la plus importante pour construire des applications 3D interactives complètes : faire dialoguer l'interface utilisateur 2D et la scène 3D.

Points clés à retenir :

  • La communication entre la 2D et la 3D se fait toujours via un état React partagé.
  • Pour des interactions simples, la remontée d'état (useState dans un parent commun) est efficace et facile à mettre en place.
  • Pour des applications complexes, le React Context est la solution la plus robuste et évolutive. Il permet de centraliser l'état et d'y accéder de n'importe où sans "prop drilling".
  • Ces patrons permettent de construire des fonctionnalités puissantes comme des configurateurs de produits, des portfolios animés au scroll, et bien plus encore.

Aperçu de la prochaine leçon :

Maintenant que nous savons créer des scènes complexes et interactives, une nouvelle préoccupation émerge : la performance. Une scène avec de nombreux objets, des lumières et des ombres peut rapidement devenir lente. Dans la prochaine leçon, nous aborderons les techniques d'optimisation essentielles pour garantir que vos applications restent fluides et réactives, même sur des appareils moins puissants. Nous parlerons de React.memo, useMemo et d'une technique cruciale en 3D : l'instanciation (InstancedMesh).