This implementation follows a modular, scalable architecture designed for educational electronics visualization.
┌─────────────────────────────────────────┐
│ UI Layer (React Components) │
│ - CircuitLab, ControlPanel, Graphs │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ 3D Rendering Layer (R3F/Three.js) │
│ - Component3D, Wire3D, Shaders │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Simulation Layer │
│ - CircuitSimulator, CircuitAnalyzer │
└──────────────────┬──────────────────────┘
│
┌──────────────────▼──────────────────────┐
│ Data Layer (Types & State) │
│ - Circuit, Component, Zustand Store │
└─────────────────────────────────────────┘
Purpose: Type definitions and interfaces Key Exports:
ComponentType: Enum for all electronic componentsComponent: Individual component definitionCircuit: Complete circuit with components and wiresSimulationState: Real-time simulation stateVisualizationOptions: Display settings
Usage:
import { Circuit, Component, ComponentType } from "@/lib/circuit/types";Purpose: Physics and circuit simulation engine Key Classes:
CircuitSimulator: Main simulation enginestep(deltaTime): Advance simulation by time deltaupdateComponentStates(): Calculate component behaviorgetComponentHistory(): Retrieve historical data
CircuitAnalyzer: Circuit analysis utilitiesnodalAnalysis(): Solve node voltagesverifyKVL(): Check Kirchhoff's voltage lawverifyKCL(): Check Kirchhoff's current law
Key Methods:
simulator.start() // Begin simulation
simulator.stop() // Pause simulation
simulator.reset() // Clear and reinitialize
simulator.step(16) // Advance 16ms
simulator.setTimeScale(2) // 2x speed
simulator.updateComponentParameter("r1", "resistance", 2000)Purpose: Global state management and visualization utilities Key Exports:
use3DStore: Zustand hook for circuit stategetComponentGeometry(): Get 3D geometry infogetComponentColor(): Calculate component colorgetCurrentFlowIntensity(): Particle flow intensitycomputeOptimalCameraPosition(): Auto-frame circuit
Usage:
const { circuit, visualization } = use3DStore();
use3DStore.setState({ selectedComponent: "r1" });Purpose: GLSL shader code for visual effects Key Shaders:
- Current flow particle animation
- Wire glow effects
- Magnetic field visualization
- Capacitor plate charging
- Diode LED emission
- Field pattern effects
Usage in Components:
<shaderMaterial
vertexShader={currentFlowParticleVertexShader}
fragmentShader={currentFlowParticleFragmentShader}
uniforms={{...}}
/>Purpose: Predefined circuit templates Key Exports:
simpleResistorCircuit: Basic Ohm's Law examplercChargingCircuit: Exponential charging demonstrationlogicGateCircuit: Digital logic showcaseblockDiagramCircuit: Control system exampleallCircuits: Array of all available circuitsgetCircuitById(): Lookup functiongetCircuitsByCategory(): Filter by category
Adding New Circuits:
export const myCircuit: Circuit = {
id: "unique-id",
name: "Circuit Name",
description: "...",
components: [...],
wires: [...],
parameters: {...},
metadata: {
category: "analog",
difficulty: "beginner",
learningObjectives: [...]
}
};Purpose: Main 3D rendering component (React Three Fiber) Key Components:
Component3D: Renders individual electronic component- Selection highlighting
- Hover effects
- Rotation animations for active components
Wire3D: Renders connections with current flow- Particle system animation
- Voltage color coding
- Current intensity visualization
CircuitVisualizer3D: Main scene container- Lighting setup
- Camera controls
- Grid visualization
Props:
<CircuitVisualizer3D
components={circuit.components}
wires={circuit.wires}
selectedComponentId={selectedId}
hoveredComponentId={hoveredId}
onComponentSelected={(id) => {}}
onComponentHovered={(id) => {}}
/>Purpose: Main page container orchestrating all components State Management:
circuit: Current circuit definitionsimulator: Active simulation engineisRunning: Play/pause stateselectedComponentId: User selectionshowGraphs: Toggle graph panel
Animation Loop:
- Uses
requestAnimationFramefor smooth 60 FPS - Calls
simulator.step()with actual delta time - Updates circuit state for re-render
Purpose: Interactive control interface (right sidebar) Sections:
- Simulation: Play, pause, reset, time scale
- Component Info: Voltage, current, power, temperature
- Visualization: Toggle display options
- Learning Mode: Formula hints, explanations, path highlighting
- Quick Reference: Common formulas in tabs
Features:
- Expandable/collapsible sections
- Smooth transitions with Framer Motion
- Real-time parameter updates
- Responsive to selected component
Purpose: Real-time data plotting with Recharts Charts:
- Voltage vs Time
- Current vs Time
- Power vs Time (area chart)
Features:
- Multi-component plotting
- Color-coded traces
- Automatic downsampling for performance
- Tooltip on hover
- Legend with component names
Purpose: Modal gallery for circuit selection Layout:
- Category tabs (Analog, Digital, Control)
- Grid of circuit cards
- Difficulty badges
- Learning objectives preview
- Info animation on hover
Purpose: Educational reference system Components:
LearningPanel: Detailed formula reference- Formulas tab with equations
- Explanation tab with descriptions
- Quick formula reference boxes
LearningTooltip: Hover-based hintsformulaReferences: Comprehensive formula database for all component types
1. Create CircuitSimulator with Circuit
2. Initialize component states
3. Set node voltages (grounds to 0V, sources to their voltage)
4. Record initial history
1. Measure deltaTime since last frame
2. Call simulator.step(deltaTime)
3. For each component:
a. Read input node voltages
b. Calculate component-specific behavior
c. Update component state (V, I, P, T)
d. Write output voltages to nodes
4. Update wire currents
5. Record historical data
6. Render updated scene
Resistor:
V = node_voltage
I = V / R
Capacitor:
I = C * dV/dt
V_new = V_old + (I / C) * dt
Inductor:
V = node_voltage
I_new = I_old + (V / L) * dt
Diode:
if V > 0.7V: // forward biased
I = (V - 0.7) / r_dynamic
else:
I = -I_leakage
BJT:
if Vbe > 0.7V: // active
I_c = β * I_b
else: // cutoff
I_c = 0
OpAmp:
V_out = A * (V_+ - V_-) (limited by supply voltage)
Nodal Analysis:
1. For each node, sum currents = 0
2. For each component, calculate current based on voltage
3. Iteratively update node voltages until convergence
Transient Response:
- Direct integration of differential equations
- Exponential solutions for linear circuits
- Numerical integration for non-linear components
- Compound Components:
CircuitLaborchestrates multiple sub-components - Controlled Components: 3D components receive data via props
- Hook-based State: Zustand store for global state
- Model-Update-Render: Simulator updates models, React renders
- Delta Time Integration: Frame-rate independent simulation
- Decoupled Physics: Component updates independent of order
- Particle System: Current flow using instanced geometry
- Material-based Feedback: Color and glow for state indication
- Shader-driven Animation: GLSL handles frame-based animations
- Extend ComponentType enum (types.ts)
export enum ComponentType {
// ...
TRANSFORMER = "transformer",
}- Add to getComponentGeometry() (store.ts)
[ComponentType.TRANSFORMER]: {
geometry: "transformer",
scale: [1.0, 1.0, 0.8],
color: "#FF8800",
}- Create geometry factory (componentGeometries.ts)
export function createTransformerGeometry(): THREE.Group {
const group = new THREE.Group();
// Create primary and secondary coils
return group;
}- Add simulation logic (simulator.ts)
case ComponentType.TRANSFORMER:
this.updateTransformer(comp, dt);
break;
private updateTransformer(comp: Component, dt: number): void {
// Implement coupled inductor equations
}- Add to component selector (scenarios.ts - optional preset)
export const newCircuit: Circuit = {
id: "unique-id",
name: "Circuit Name",
description: "What this circuit demonstrates",
components: [/* ... */],
wires: [/* ... */],
parameters: {
voltage: 5,
frequency: 0,
timeStep: 0.001,
},
metadata: {
category: "analog",
difficulty: "beginner",
learningObjectives: [
"Learning goal 1",
"Learning goal 2",
],
},
};
// Add to allCircuits array
export const allCircuits = [
simpleResistorCircuit,
newCircuit, // <- Add here
];Theme Configuration (in ControlPanel and CircuitLab):
// Dark theme (default)
className="bg-slate-900 text-purple-400"
// Light theme (add as variant)
className="bg-slate-100 text-purple-600"
// High contrast (add as accessibility option)
className="bg-black text-lime-400"-
Memory Management
- History buffer capped at 10,000 points
- Old entries automatically removed (FIFO)
- Prevents memory leaks in long simulations
-
Render Optimization
- Component geometries created once, reused
- Instanced rendering for similar components
- LOD system (disabled for small circuits)
-
Shader Efficiency
- Minimal texture lookups
- Early fragment discard for invisible areas
- Pre-compiled material templates
-
Data Structures
- Sparse component state updates
- Efficient wire path calculations
- Memoized getter functions
Browser DevTools:
- Open Chrome DevTools → Performance tab
- Start recording
- Let simulation run for 5-10 seconds
- Stop and analyze:
- Look for long frames (>16.67ms for 60 FPS)
- Identify bottleneck functions
- Check memory heap size
Typical Metrics:
- Frame time: 5-12ms (60+ FPS)
- Memory: 50-150MB
- GPU utilization: 20-40% (simple circuits)
- Check if
simulatoris initialized - Verify
isRunningstate is true - Check console for JavaScript errors
- Verify components have valid connections
- Ensure simulation has been running long enough
- Check
simulationState.historyhas data - Verify component IDs match between circuit and graph
- Reduce number of wires in circuit
- Disable graph rendering on complex circuits
- Lower time resolution in graphs
- Check for memory leaks via DevTools
- Circuit loads without errors
- Play/Pause buttons work
- Time scale slider responds
- Components highlight on selection
- Graphs update in real-time
- Circuit selector loads all circuits
- Control panel responsive to component selection
- Smooth 60 FPS animation
- No memory leaks after 5 minute run
describe("CircuitSimulator", () => {
it("should initialize with zero state", () => {
const circuit = simpleResistorCircuit;
const sim = new CircuitSimulator(circuit);
sim.initialize();
expect(sim.getState().time).toBe(0);
});
it("should calculate Ohm's Law correctly", () => {
// V = IR, given V=5, R=1000
// I should be 5/1000 = 0.005A
});
});npm run build- All dependencies installed
- No console errors
- Tested on target browsers
- Images/assets included
- Performance acceptable (60 FPS)
- Mobile responsiveness (for future)
This implementation provides a solid foundation for interactive electronics education with room for extensions and optimizations.