Viewer 3D de Molécules
Vue d'ensemble
Visualiseur 3D interactif de molécules chimiques, accessible via /projects/molecule-viewer. Combine un catalogue de molécules prédéfinies avec une recherche libre via l'API PubChem, le tout rendu en WebGL avec Three.js/React Three Fiber.
Public cible : étudiants en chimie, chercheurs, curieux de sciences. Contexte : projet personnel démontrant l'intégration de Three.js dans Next.js (App Router) et la consommation d'une API scientifique externe.
Ressources clés
- Three.js docs —
SphereGeometry,CylinderGeometry,MeshStandardMaterial,Vector3 - @react-three/fiber (R3F) — abstraction React de Three.js,
<Canvas>,useFrame,useThree - @react-three/drei —
<OrbitControls>,<Environment>, helpers haut niveau pour R3F - PubChem REST API — documentation complète de l'API publique
- Compound JSON3D — format de réponse pour les conformères 3D
- Name → CID search — endpoint de recherche par nom
- CPK coloring — Wikipedia — convention de couleur des atomes (C=gris, H=blanc, O=rouge...)
- Next.js
dynamic+ssr: false— chargement conditionnel côté client uniquement - React
useReducer— gestion de l'état du mode mesure (sélection de 2 atomes) - WebGL context limits — limite de contextes WebGL simultanés (pertinent sur mobile)
Stack technique
| Lib | Usage |
|---|---|
| React 19 + Next.js App Router | Rendu, routing |
| Three.js | Rendu 3D WebGL bas niveau |
| @react-three/fiber | Abstraction React de Three.js |
| @react-three/drei | Helpers R3F (OrbitControls, etc.) |
| TypeScript strict | Typage des atomes, liaisons, settings |
| PubChem REST API | Récupération de structures moléculaires au format JSON3D |
| Tailwind CSS v4 | Interface UI |
MoleculeScene est chargé en dynamic avec ssr: false — Three.js requiert le DOM navigateur, incompatible avec le SSR Next.js.
Architecture
src/app/projects/molecule-viewer/
page.tsx # Interface principale : sélection, recherche, paramètres, mode mesure
MoleculeScene.tsx # Canvas R3F : rendu 3D des atomes et liaisons
layout.tsx # Metadata Next.js
opengraph-image.tsx
Flux de données
page.tsx
├── Catalogue MOLECULES (statique inline) → sélection par défaut
├── Recherche PubChem → fetch → parse → SceneMolecule
└── SceneMolecule/SceneSettings → props vers MoleculeScene
└── Canvas R3F
├── Sphères (atomes)
├── Cylindres (liaisons)
└── OrbitControls
Types partagés (MoleculeScene.tsx)
interface SceneAtom {
element: string; // "C", "H", "O", etc.
position: [number, number, number];
index: number;
}
interface SceneMolecule {
atoms: SceneAtom[];
bonds: [number, number][]; // paires d'indices d'atomes
}
interface SceneSettings {
accentColor: string;
cameraZ: number;
measureMode: boolean;
}
Fonctionnalités
Catalogue de molécules prédéfinies
10 molécules hardcodées dans MOLECULES (tableau as const) avec pour chacune :
id— identifiant internename/formula— affichage FR (+ tableMOLECULE_ENpour les noms/descriptions EN)cid— identifiant PubChem pour le fetch des coordonnées 3DmolarMass— masse molaire affichéecameraZ— distance initiale caméra (adaptée à la taille de la molécule)accentColor— couleur d'accent de la fiche (différente par molécule)description— texte chimique descriptif (FR inline, EN dansMOLECULE_EN)
Molécules disponibles : Eau, Éthanol, Benzène, Caféine, Aspirine, Dopamine, Glycine, Acide pyruvique, Propionitrile, Nicotinamide.
Récupération des structures 3D (PubChem)
Lors de la sélection d'une molécule (catalogue ou recherche), la page fetch :
https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cid}/JSON?record_type=3d
La réponse est parsée pour extraire :
- Les atomes (
atoms.element,coords[0].conformers[0]→ x/y/z) - Les liaisons (
bonds.aid1[i],bonds.aid2[i]→ paires d'indices)
Recherche libre PubChem
Un champ de recherche permet de chercher n'importe quelle molécule par nom (en anglais). Le flux :
- Fetch
https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{query}/cids/JSON→ liste de CIDs - Fetch du premier CID trouvé en mode 3D
- Mise à jour de la scène
Affichage d'un état de chargement // recherche en cours… et d'un message d'erreur si aucun résultat.
Rendu 3D (MoleculeScene)
- Atomes : sphères Three.js avec coloration CPK (C=gris, H=blanc, O=rouge, N=bleu, S=jaune, etc.)
- Liaisons : cylindres entre les atomes liés
- OrbitControls : rotation (drag), zoom (scroll), déplacement (clic droit)
- Éclairage : lumière ambiante + directionnelle
Mode mesure
Activé via le bouton ⟷ Mesure. En mode mesure :
- Le clic sur deux atomes successifs calcule et affiche la distance interatomique en Angströms (Å)
- Implémenté via un
useReducergérant l'étatselectedAtoms: [number, number] | [number]
Paramètres de scène
Contrôlés depuis page.tsx et passés en props :
showHydrogens— affichage/masquage des hydrogènesbondStyle— style de liaisons (stick / ball-and-stick)accentColor— couleur d'accent héritée de la molécule sélectionnée
i18n
- Toutes les chaînes UI sont dans
i18n/fr.tseti18n/en.tssous la clémolecule_viewer.* - Le composant importe
{ fr as frStrings }et{ en as enStrings }directement (pasuseLang()) car il possède son propre toggle de langue indépendant du contexte global - Les noms et descriptions des molécules prédéfinies : FR inline dans
MOLECULES, EN dansMOLECULE_EN(données, pas UI) - Les molécules issues de PubChem n'ont pas de traduction (données brutes de l'API)
- Les strings avec paramètres (ex.
"// {n} atomes") utilisent.replace("{n}", ...)dans le JSX
Points d'attention
- SSR :
MoleculeScenedoit absolument être chargé avecdynamic(..., { ssr: false }). Three.js accède au DOM (window,canvas) au montage. - PubChem rate limiting : l'API publique n'a pas de clé d'authentification mais limite les requêtes. En cas d'usage intensif, envisager un cache côté serveur.
- Coordonnées 3D : PubChem ne fournit pas toujours les coordonnées 3D (conformères) pour toutes les molécules. En cas d'absence, le fetch échoue silencieusement et affiche
// erreur. - Recherche en anglais uniquement : l'API PubChem répond principalement aux noms IUPAC anglais. Le hint UI le précise.
- Mémoire WebGL : chaque changement de molécule recrée la scène Three.js. Sur mobile, les contextes WebGL multiples peuvent être problématiques.
Évolutions possibles
- Affichage du nom IUPAC et de la formule brute pour les molécules recherchées
- Mode "comparer deux molécules" (split screen)
- Coloration par électronégativité ou charge partielle
- Export de capture d'écran de la scène 3D (
canvas.toDataURL()) - Cache localStorage des CIDs récemment consultés
- Mode "surfaces de van der Waals" (sphères aux rayons CPK réels)
- Annotation des liaisons (affichage de la longueur en Å au survol)