Use Cases (Mis à jour: 02/06/2026)

Three.js 3D avec Claude Code : guide pratique Web UI

Créez un viewer 3D avec Claude Code et Three.js, avec resize, cleanup, revue technique et cas d'usage.

Three.js 3D avec Claude Code : guide pratique Web UI

Three.js rend WebGL plus accessible, mais une interface 3D prête pour la production n’est pas seulement un objet qui tourne. Il faut aussi gérer la caméra, la lumière, la taille du canvas, la charge GPU sur mobile, le nettoyage des ressources et le comportement quand un modèle ne se charge pas.

Claude Code est très utile pour générer cette base rapidement. Le risque est de demander seulement “fais une scène 3D élégante”. On obtient alors souvent une démo séduisante, mais pas forcément un composant robuste : canvas blanc après un changement de layout, fuite mémoire après navigation, ou scène trop lourde pour un téléphone.

Ce guide montre une base Vite + React + Three.js copiable, puis les consignes de revue à donner à Claude Code avant publication.

Définir le rôle du 3D

Avant le code, il faut définir ce que l’utilisateur doit comprendre grâce au 3D. Pour un viewer produit, il peut s’agir de la couleur, de la texture, du dos de l’objet ou de l’impression d’échelle. Pour une visualisation de données, l’objectif peut être de voir des groupes, des valeurs atypiques ou une évolution temporelle. Pour une scène éducative, il faut souvent guider l’attention vers une pièce précise.

Un bon prompt pour Claude Code contient des contraintes concrètes.

Crée un viewer produit 3D avec Vite + React + TypeScript + three.
Contraintes:
- rendre le canvas dans un élément parent, pas dans document.body
- suivre la taille du conteneur
- activer rotation et zoom avec OrbitControls
- disposer geometry, material, renderer et controls au démontage
- limiter devicePixelRatio à 2 sur mobile
- fournir un code copiable dans src/App.tsx

Ces contraintes forment le harness, c’est-à-dire l’échafaudage qui aide l’agent à travailler sans casser l’application. Elles évitent les problèmes classiques : canvas blanc, image déformée, renderer encore actif après navigation et surcharge GPU. Pour vérifier les API, utilisez la documentation officielle Three.js et la page WebGLRenderer.

Mise en place Vite/React minimale

Commencez avec Three.js directement dans React. React Three Fiber peut être excellent, mais voir le cycle de vie brut aide à comprendre les erreurs : créer le renderer, l’ajouter au DOM, écouter resize, animer, puis libérer les ressources.

npm create vite@latest three-claude-demo -- --template react-ts
cd three-claude-demo
npm i three
npm run dev
flowchart LR
  A["React component"] --> B["mount div"]
  B --> C["WebGLRenderer canvas"]
  C --> D["Scene"]
  D --> E["Camera and lights"]
  D --> F["Mesh and material"]
  C --> G["OrbitControls"]
  G --> H["resize and dispose"]

Viewer 3D copiable

Collez ce code dans src/App.tsx. Il crée un objet de démonstration, ajoute lumière et contrôle caméra, suit la taille du conteneur et nettoie les ressources Three.js lors du démontage.

import { useEffect, useRef } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import "./App.css";

export default function App() {
  const mountRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const mount = mountRef.current;
    if (!mount) return;

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0xf6f7fb);

    const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 100);
    camera.position.set(3.5, 2.2, 4.5);

    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.outputColorSpace = THREE.SRGBColorSpace;
    renderer.shadowMap.enabled = true;
    mount.appendChild(renderer.domElement);

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.minDistance = 2.5;
    controls.maxDistance = 8;
    controls.target.set(0, 0.4, 0);

    scene.add(new THREE.HemisphereLight(0xffffff, 0x7c8594, 1.6));

    const keyLight = new THREE.DirectionalLight(0xffffff, 2.4);
    keyLight.position.set(3, 5, 4);
    keyLight.castShadow = true;
    scene.add(keyLight);

    const productGeometry = new THREE.BoxGeometry(1.8, 1.2, 1.1, 4, 4, 4);
    const productMaterial = new THREE.MeshStandardMaterial({
      color: 0x2f6f73,
      roughness: 0.42,
      metalness: 0.08,
    });
    const product = new THREE.Mesh(productGeometry, productMaterial);
    product.castShadow = true;
    product.position.y = 0.75;
    scene.add(product);

    const floorGeometry = new THREE.CircleGeometry(2.2, 64);
    const floorMaterial = new THREE.MeshStandardMaterial({
      color: 0xd9dee8,
      roughness: 0.7,
    });
    const floor = new THREE.Mesh(floorGeometry, floorMaterial);
    floor.rotation.x = -Math.PI / 2;
    floor.receiveShadow = true;
    scene.add(floor);

    const resize = () => {
      const width = mount.clientWidth;
      const height = mount.clientHeight;
      if (width === 0 || height === 0) return;

      camera.aspect = width / height;
      camera.updateProjectionMatrix();
      renderer.setSize(width, height, false);
    };

    let frameId = 0;
    const clock = new THREE.Clock();

    const animate = () => {
      const elapsed = clock.getElapsedTime();
      product.rotation.y = elapsed * 0.45;
      product.rotation.x = Math.sin(elapsed * 0.8) * 0.08;
      controls.update();
      renderer.render(scene, camera);
      frameId = window.requestAnimationFrame(animate);
    };

    resize();
    animate();
    window.addEventListener("resize", resize);

    return () => {
      window.removeEventListener("resize", resize);
      window.cancelAnimationFrame(frameId);
      controls.dispose();

      scene.traverse((object) => {
        if (object instanceof THREE.Mesh) {
          object.geometry.dispose();
          const materials = Array.isArray(object.material)
            ? object.material
            : [object.material];
          materials.forEach((material) => material.dispose());
        }
      });

      renderer.dispose();
      renderer.domElement.remove();
    };
  }, []);

  return (
    <main className="viewerShell">
      <div className="copy">
        <p className="eyebrow">Three.js + Claude Code</p>
        <h1>3D product viewer</h1>
        <p>
          Drag to rotate, scroll to zoom, and resize the window to verify that
          the canvas follows its container.
        </p>
      </div>
      <div ref={mountRef} className="viewerStage" />
    </main>
  );
}

Ajoutez ce CSS dans src/App.css. La hauteur du conteneur est essentielle : sans elle, le canvas peut exister mais rester invisible.

body {
  margin: 0;
  font-family: Inter, system-ui, sans-serif;
  background: #eef2f7;
  color: #17202a;
}

.viewerShell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(260px, 0.8fr) minmax(320px, 1.2fr);
  gap: 32px;
  align-items: center;
  padding: 40px;
  box-sizing: border-box;
}

.copy {
  max-width: 520px;
}

.viewerStage {
  height: min(62vh, 560px);
  min-height: 360px;
  border: 1px solid #ccd5df;
  background: #f6f7fb;
}

.viewerStage canvas {
  display: block;
}

@media (max-width: 760px) {
  .viewerShell {
    grid-template-columns: 1fr;
    padding: 24px;
  }

  .viewerStage {
    min-height: 300px;
  }
}

Demander une revue à Claude Code

Après l’implémentation, demandez une revue orientée risques.

Relis cette implémentation React + Three.js.
Vérifie:
1. le canvas suit bien la taille du conteneur
2. geometry, material, renderer et controls sont libérés au démontage
3. requestAnimationFrame est arrêté
4. devicePixelRatio reste raisonnable sur mobile
5. window/document ne cassent pas SSR dans Next.js ou Astro
6. caméra, lumières et contrôles servent vraiment l'inspection produit
Retourne des diffs précis et une checklist de test manuel.

Cette revue est utile car les fuites de ressources ne se voient pas toujours à l’écran. Naviguez plusieurs fois, puis regardez Memory et Performance dans DevTools.

Trois cas d’usage utiles

CasPourquoi utiliser la 3DTravail à demander à Claude Code
Viewer produitVérifier couleur, finition, volume et faces cachéesOrbitControls, variantes, lumières, test mobile
Visualisation de donnéesMontrer groupes, anomalies ou mouvements temporelsnuage de points, barres 3D, transitions caméra, légendes
Portfolio ou éducationExpliquer une structure avec un modèle manipulablelabels, surbrillance des pièces, vues guidées

Pour un produit, la 3D doit réduire l’hésitation d’achat. Pour les données, elle doit améliorer la lecture, sinon une vue 2D reste nécessaire. Pour l’éducation, la liberté de rotation ne suffit pas : prévoyez une séquence, des labels et des positions de caméra.

Erreurs fréquentes et corrections

ErreurCause probableCorrection
Canvas blanchauteur parent nulle, caméra mal placée, manque de lumièrefixer la hauteur CSS, vérifier camera position et controls target
Image déformée après resizecamera.aspect et renderer size ne sont pas mis à jour ensembleappeler camera.updateProjectionMatrix() et renderer.setSize()
Page plus lente après navigationdispose manquant sur resources Three.jsparcourir la scene au démontage et libérer geometry/material
Mobile qui chauffepixel ratio élevé, ombres chères, modèle trop denselimiter pixelRatio, réduire ombres et segments
Crash SSRaccès à window/document pendant le rendu serveurinitialiser dans useEffect ou un composant client-only

Pour déboguer un écran blanc, revenez à un cube, une lumière et un fond clair. Ne mélangez pas en même temps GLB, HDR, post-traitement et problème de layout.

Publication et accompagnement

Avant publication, testez le téléphone le plus faible que vous devez supporter. Vérifiez fps, température, taille du modèle, image de secours si WebGL échoue et texte alternatif pour comprendre la scène. Pour l’architecture canvas, consultez le guide Canvas avec Claude Code. Pour le mouvement, lisez aussi le guide animation avec Claude Code.

Claude Code Lab peut accompagner la revue de viewers produit 3D, de visualisations WebGL et de scènes éducatives, ou former une équipe aux prompts de revue. Préparez les appareils cibles, le framework, le format des modèles, le budget de performance et la raison métier de la 3D.

Résultat testé

J’ai collé le code dans un projet Vite React TypeScript, puis testé les tailles desktop et mobile. La hauteur explicite de .viewerStage évite le canvas blanc. La limite devicePixelRatio à 2 réduit le travail GPU inutile sur écrans denses. La revue de Claude Code sur le chemin de dispose aide aussi à repérer les fuites avant de considérer la démo publiable.

#Claude Code #Three.js #3D #WebGL #frontend
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.