W niniejszym artykule poddam weryfikacji możliwości modelu Gemini w kontekście generowania symulacji Układu Słonecznego. Projekt zostanie zrealizowany w oparciu o z góry określony stos technologiczny obejmujący: React, Three.js oraz TypeScript.
Zaczynam od wysłania requestu do Gemini:
I want to create solar system with react and three.js I want to use typescript. Draw planets as cartoon and funny objects. I need step by step how to create application. Add zoom in and zoom out functionality. Add label on every planet.
Poniżej wklejam kolejne polecenia otrzymane z Gemini.
Step 1: Set up the Project
First, create a new React application with TypeScript and install the necessary 3D libraries. Open your terminal and run:
# 1. Create the app (using Vite is faster/modern, but Create React App works too) npm create vite@latest solar-system -- --template react-ts cd solar-system # 2. Install Three.js and React Three Fiber ecosystem npm install three @types/three @react-three/fiber @react-three/drei
Step 2: Clean up CSS
Make sure your canvas takes up the full screen. Open src/index.css (or App.css) and replace the content with this:
html, body, #root {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background: #111; /* Dark space background */
overflow: hidden;
}
Step 3: Create the Application
We will build this in a single file (App.tsx) for simplicity, but in a real app, you would split these into separate files.
Key concepts we are using:
MeshToonMaterial: This gives the planets a „cel-shaded” or cartoonish look rather than a realistic one.@react-three/drei/Html: This lets us stick standard HTML text (labels) to 3D objects easily.useFrame: This hook runs 60 times a second, allowing us to animate the planets orbiting.
Copy the following code into src/App.tsx:
import React, { useRef, useState } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, Html, Stars } from '@react-three/drei';
import * as THREE from 'three';
// --- Types ---
interface PlanetProps {
name: string;
color: string;
size: number;
distance: number;
speed: number;
hasRing?: boolean;
}
// --- Planet Component ---
const Planet: React.FC<PlanetProps> = ({ name, color, size, distance, speed, hasRing }) => {
// References to the mesh (for self-rotation) and the group (for orbit)
const planetRef = useRef<THREE.Mesh>(null);
const orbitRef = useRef<THREE.Group>(null);
// State for hover effect
const [hovered, setHover] = useState(false);
// Animation Loop: Runs every frame
useFrame((state, delta) => {
// 1. Self-rotation (Spinning on axis)
if (planetRef.current) {
planetRef.current.rotation.y += delta * 0.5;
}
// 2. Orbit rotation (Revolving around the sun)
if (orbitRef.current) {
orbitRef.current.rotation.y += delta * speed;
}
});
return (
<group ref={orbitRef}>
{/* We offset the planet by 'distance' on the X axis.
Because this group rotates at the center (0,0,0), the planet will orbit.
*/}
<mesh
ref={planetRef}
position={[distance, 0, 0]}
onPointerOver={() => setHover(true)}
onPointerOut={() => setHover(false)}
onClick={() => console.log(`You clicked ${name}!`)}
>
{/* 'toon' material gives it the cartoon look */}
<sphereGeometry args={[size, 32, 32]} />
<meshToonMaterial color={hovered ? 'white' : color} />
{/* OPTIONAL: Ring for Saturn-like planets */}
{hasRing && (
<mesh rotation={[-Math.PI / 2, 0, 0]}>
<torusGeometry args={[size * 1.5, 0.2, 16, 100]} />
<meshToonMaterial color="orange" />
</mesh>
)}
{/* Text Label */}
<Html distanceFactor={15}>
<div className="label-content">
{name}
</div>
</Html>
</mesh>
</group>
);
};
// --- Sun Component ---
const Sun = () => {
return (
<mesh>
<sphereGeometry args={[2.5, 32, 32]} />
{/* Emissive makes it glow, standard material is fine here */}
<meshStandardMaterial emissive="#FFD700" emissiveIntensity={2} color="#FFD700" />
<pointLight intensity={200} distance={100} decay={2} color="white" />
<Html distanceFactor={20}>
<div className="label-content" style={{ color: 'yellow', fontWeight: 'bold' }}>SUN</div>
</Html>
</mesh>
);
};
// --- Main App Component ---
function App() {
return (
<>
{/* Canvas is the entry point for Three.js.
'camera' sets the default zoom level.
*/}
<Canvas camera={{ position: [0, 20, 25], fov: 45 }}>
{/* --- Lighting is crucial for Toon Material --- */}
<ambientLight intensity={0.5} />
<directionalLight position={[10, 10, 5]} intensity={1} />
{/* --- Background Stars --- */}
<Stars radius={100} depth={50} count={5000} factor={4} saturation={0} fade speed={1} />
{/* --- Solar System Objects --- */}
<Sun />
{/* Props Explanation:
distance: How far from center (sun)
speed: Orbit speed (lower is slower)
size: Radius of the planet
*/}
<Planet name="Mercury" color="#A5A5A5" size={0.4} distance={5} speed={0.8} />
<Planet name="Venus" color="#FFC107" size={0.7} distance={8} speed={0.6} />
<Planet name="Earth" color="#2196F3" size={0.8} distance={12} speed={0.4} />
<Planet name="Mars" color="#FF5722" size={0.6} distance={16} speed={0.3} />
<Planet name="Jupiter" color="#FF9800" size={1.8} distance={22} speed={0.15} />
<Planet name="Saturn" color="#E6C17B" size={1.5} distance={30} speed={0.1} hasRing={true} />
{/* --- Controls --- */}
{/* OrbitControls gives you Zoom (scroll), Rotate (drag), and Pan (right-click drag) automatically */}
<OrbitControls enablePan={true} enableZoom={true} enableRotate={true} />
</Canvas>
</>
);
}
export default App;
Step 4: Add Simple Styles for the Labels
Because we used the <Html> component, we can style the labels using standard CSS. Add this to your src/index.css file to make the labels look „cartoonish” and readable:
.label-content {
background: rgba(0, 0, 0, 0.7);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-family: 'Comic Sans MS', 'Chalkboard SE', sans-serif; /* Cartoon font */
font-size: 12px;
white-space: nowrap;
pointer-events: none; /* Let clicks pass through to the planet */
border: 1px solid white;
}
Step 5: Run It
Back in your terminal, start the development server:
npm run dev
Wynik końcowy

Rzut oka na obrazek powyżej i werdykt jest jasny: sukces, ale nie w 100%. Mechanika działa, układ się kręci, ale… gdzieś zgubiło się kilka planet. Na szczęście to drobiazg. Mamy teraz dwie drogi: dopisać resztę ciał niebieskich samodzielnie albo wysłać Gemini z powrotem do pracy z prośbą o poprawkę.