The atom visualization feature creates interactive SVG diagrams showing the nucleus and electron distribution across energy levels.
Rendering atoms with SVG
The renderAtom() function generates dynamic atomic models based on electron configuration:
export const renderAtom = (containerId, atomicNumber, symbol) => {
const container = document.getElementById(containerId);
if (!container) return;
const electronsByLevel = getElectronsPerLevel(atomicNumber);
const maxLevel = Math.max(...Object.keys(electronsByLevel).map(Number));
const viewBoxSize = (orbitRadii[maxLevel] || 180) * 2 + 40;
const centerOffset = viewBoxSize / 2;
// ...
}
Orbit radii configuration
Electron shells are positioned at fixed radii from the nucleus:
const orbitRadii = {
1: 30, // First shell (K)
2: 60, // Second shell (L)
3: 90, // Third shell (M)
4: 120, // Fourth shell (N)
5: 150, // Fifth shell (O)
6: 180 // Sixth shell (P)
};
Each shell radius increases by 30 units to maintain visual clarity and proper spacing between orbital levels.
Electron positioning algorithm
Electrons are distributed evenly around each orbital using trigonometric calculations:
const getElectronPositions = (radius, count) => {
const positions = [];
for (let i = 0; i < count; i++) {
const angle = (i / count) * 2 * Math.PI;
positions.push({
x: radius * Math.cos(angle),
y: radius * Math.sin(angle)
});
}
return positions;
};
How electron spacing works
- Calculates angular increment as
2π / electron count to divide the circle evenly
- For each electron, computes its angle:
angle = (index / total) * 2π
- Converts polar coordinates to Cartesian:
x = r * cos(θ), y = r * sin(θ)
- Returns array of
{x, y} position objects
This algorithm ensures electrons are always evenly spaced regardless of how many occupy the orbital, creating a balanced visual representation.
SVG structure
The atom visualization builds an SVG with three main components:
1. Nucleus
svgContent = `
<circle cx="0" cy="0" r="15" class="fill-indigo-700" />
<text x="0" y="5" text-anchor="middle" class="fill-white text-[10px] font-bold">${symbol}</text>
`;
The nucleus is rendered as a 15-unit radius circle at the origin with the element symbol centered inside.
2. Orbital paths
svgContent += `<circle cx="0" cy="0" r="${radius}" class="stroke-slate-300 stroke-[0.5px] fill-none" />`;
Each occupied shell is drawn as a thin circular outline showing the electron orbital path.
3. Electrons
positions.forEach(pos => {
svgContent += `<circle cx="${pos.x}" cy="${pos.y}" r="5" class="fill-indigo-400 stroke-indigo-600 stroke-[1px]" />`;
});
Electrons appear as 5-unit radius circles positioned at calculated coordinates with distinct coloring.
Dynamic viewBox sizing
The SVG viewBox automatically adjusts based on the atom’s size:
const maxLevel = Math.max(...Object.keys(electronsByLevel).map(Number));
const viewBoxSize = (orbitRadii[maxLevel] || 180) * 2 + 40;
const centerOffset = viewBoxSize / 2;
This ensures atoms with more electron shells receive appropriately larger canvas dimensions while maintaining centered composition.
Visual styling
<circle r="15" class="fill-indigo-700" />
<text class="fill-white text-[10px] font-bold">{symbol}</text>
The color scheme uses indigo tones for structure with light gray orbitals, creating clear visual hierarchy.
Integration with UI
Atom visualizations are rendered into placeholder containers defined by the AtomViewer component:
<div
id={id}
class="flex flex-col items-center p-4 bg-white rounded-xl shadow-md min-h-[300px] justify-center"
>
<p class="text-slate-400 italic">Esperando cálculo...</p>
</div>
When renderAtom() executes, it replaces the placeholder content with the complete atomic visualization including title and SVG diagram.