feat: implement interactive Periodic Table (PSE) modal with Bohr atom models and Steckbrief details
This commit is contained in:
parent
e193638b70
commit
d2253bfac3
216
app.js
216
app.js
@ -6,14 +6,23 @@ const discoveryProgress = document.getElementById('discovery-progress');
|
||||
const atomCountEl = document.getElementById('atom-count');
|
||||
const moleculeCountEl = document.getElementById('molecule-count');
|
||||
|
||||
// Modal Elements
|
||||
// Main Modal Elements
|
||||
const infoModal = document.getElementById('info-modal');
|
||||
const modalTitle = document.getElementById('modal-title');
|
||||
const modalFormula = document.getElementById('modal-formula-badge');
|
||||
const modalName = document.getElementById('modal-molecule-name');
|
||||
const modalDesc = document.getElementById('modal-description');
|
||||
const modalCloseBtn = document.getElementById('modal-close-btn');
|
||||
const modalOverlay = document.querySelector('.modal-overlay');
|
||||
const modalOverlay = document.querySelector('#info-modal .modal-overlay');
|
||||
const modalCloseIcon = document.querySelector('#info-modal .modal-close-icon');
|
||||
|
||||
// PSE Modal Elements
|
||||
const pseToggleBtn = document.getElementById('pse-toggle-btn');
|
||||
const pseModal = document.getElementById('pse-modal');
|
||||
const pseCloseBtn = document.getElementById('pse-close-btn');
|
||||
const pseCloseIcon = document.getElementById('pse-close-icon');
|
||||
const pseOverlay = document.querySelector('#pse-modal .modal-overlay');
|
||||
const pseSpawnBtn = document.getElementById('pse-spawn-btn');
|
||||
|
||||
let elementsOnDesk = [];
|
||||
let draggingElement = null;
|
||||
@ -23,6 +32,7 @@ let offsetY = 0;
|
||||
// Elemente Datenbank für Spawnen (Symbole, Farben, Namen)
|
||||
const elementDetails = {
|
||||
'H': { color: '#ff7675', name: 'Wasserstoff' },
|
||||
'He': { color: '#e84393', name: 'Helium' },
|
||||
'O': { color: '#74b9ff', name: 'Sauerstoff' },
|
||||
'C': { color: '#2d3436', name: 'Kohlenstoff' },
|
||||
'N': { color: '#a29bfe', name: 'Stickstoff' },
|
||||
@ -32,6 +42,31 @@ const elementDetails = {
|
||||
'Fe': { color: '#b2bec3', name: 'Eisen' }
|
||||
};
|
||||
|
||||
// Periodensystem Elemente Datenbank (Wissenschaftliche Details & Schalenmodell)
|
||||
const pseElements = [
|
||||
{ number: 1, symbol: 'H', name: 'Wasserstoff', mass: '1.008 u', category: 'nichtmetall', row: 1, col: 1, playable: true, electrons: [1], desc: 'Das häufigste und leichteste Element im Universum. Es bildet den primären Kernbrennstoff für alle leuchtenden Sterne.' },
|
||||
{ number: 2, symbol: 'He', name: 'Helium', mass: '4.003 u', category: 'edelgas', row: 1, col: 18, playable: true, electrons: [2], desc: 'Ein absolut reaktionsträges Edelgas. Es brennt nicht und ist viel leichter als Luft – perfekt für Ballons und lässt Stimmen lustig hoch klingen!' },
|
||||
{ number: 3, symbol: 'Li', name: 'Lithium', mass: '6.94 u', category: 'alkalimetall', row: 2, col: 1, playable: false, electrons: [2, 1], desc: 'Ein extrem leichtes, reaktives Metall. Es ist das Herzstück moderner Lithium-Ionen-Akkus für Handys, Laptops und Elektroautos.' },
|
||||
{ number: 4, symbol: 'Be', name: 'Beryllium', mass: '9.012 u', category: 'erdalkali', row: 2, col: 2, playable: false, electrons: [2, 2], desc: 'Ein seltenes, hochgiftiges Erdalkalimetall. Es ist extrem steif und temperaturbeständig und wird deshalb im Weltraumteleskop-Bau (z.B. James Webb) eingesetzt.' },
|
||||
{ number: 5, symbol: 'B', name: 'Bor', mass: '10.81 u', category: 'metalloid', row: 2, col: 13, playable: false, electrons: [2, 3], desc: 'Ein hartes, hitzebeständiges Halbmetall. Es wird für extrem widerstandsfähiges Glas (Borosilikatglas) und im Raketentreibstoff-Sektor verwendet.' },
|
||||
{ number: 6, symbol: 'C', name: 'Kohlenstoff', mass: '12.011 u', category: 'nichtmetall', row: 2, col: 14, playable: true, electrons: [2, 4], desc: 'Die chemische Basis allen Lebens auf der Erde! Kohlenstoff kommt in reiner Form sowohl als weicher Graphit (Bleistift) als auch als extrem harter Diamant vor.' },
|
||||
{ number: 7, symbol: 'N', name: 'Stickstoff', mass: '14.007 u', category: 'nichtmetall', row: 2, col: 15, playable: true, electrons: [2, 5], desc: 'Stickstoff bildet fast 78% unserer Atemluft! Er reagiert unter normalen Bedingungen kaum und schützt die Erde vor unkontrollierbaren Bränden.' },
|
||||
{ number: 8, symbol: 'O', name: 'Sauerstoff', mass: '15.999 u', category: 'nichtmetall', row: 2, col: 16, playable: true, electrons: [2, 6], desc: 'Lebensnotwendig für fast alle Tiere. Es ist hochreaktiv und verbindet sich leidenschaftlich gern mit anderen Elementen (Rosten von Eisen, Verbrennung).' },
|
||||
{ number: 9, symbol: 'F', name: 'Fluor', mass: '18.998 u', category: 'halogen', row: 2, col: 17, playable: false, electrons: [2, 7], desc: 'Das reaktivste aller chemischen Elemente! Fluor-Gas zerfrisst fast jeden Stoff sofort unter Flammenbildung. Spuren von Fluorid schützen unseren Zahnschmelz.' },
|
||||
{ number: 10, symbol: 'Ne', name: 'Neon', mass: '20.180 u', category: 'edelgas', row: 2, col: 18, playable: false, electrons: [2, 8], desc: 'Ein extrem reaktionsträges Edelgas. Unter Hochspannung leuchtet es intensiv rötlich-orange, weshalb es der Namensgeber für alle Leuchtreklamen ist.' },
|
||||
{ number: 11, symbol: 'Na', name: 'Natrium', mass: '22.990 u', category: 'alkalimetall', row: 3, col: 1, playable: true, electrons: [2, 8, 1], desc: 'Ein extrem reaktionsfreudiges, weiches Alkalimetall. Es reagiert explosionsartig mit Wasser und muss daher in zähem Öl (Petroleum) gelagert werden.' },
|
||||
{ number: 12, symbol: 'Mg', name: 'Magnesium', mass: '24.305 u', category: 'erdalkali', row: 3, col: 2, playable: false, electrons: [2, 8, 2], desc: 'Ein leichtes Erdalkalimetall. Es brennt mit einer extrem hellen, blendend weißen Flamme und ist wichtig für die Muskel- und Nervenfunktion im Körper.' },
|
||||
{ number: 13, symbol: 'Al', name: 'Aluminium', mass: '26.982 u', category: 'metall', row: 3, col: 13, playable: false, electrons: [2, 8, 3], desc: 'Das dritthäufigste Element der Erdkruste. Es ist leicht, rostfrei und wird für Flugzeuge, Alufolie, Getränkedosen und Autoteile verwendet.' },
|
||||
{ number: 14, symbol: 'Si', name: 'Silicium', mass: '28.085 u', category: 'metalloid', row: 3, col: 14, playable: false, electrons: [2, 8, 4], desc: 'Das Element, das unsere Computertechnologie antreibt! Silicium ist ein Halbleiter und die absolute Basis aller Mikrochips und Solarzellen.' },
|
||||
{ number: 15, symbol: 'P', name: 'Phosphor', mass: '30.974 u', category: 'nichtmetall', row: 3, col: 15, playable: false, electrons: [2, 8, 5], desc: 'Ein lebenswichtiges Element, das im menschlichen Erbgut (DNA) und in Knochen vorkommt. Roter Phosphor wird auf Streichholz-Reibflächen verwendet.' },
|
||||
{ number: 16, symbol: 'S', name: 'Schwefel', mass: '32.06 u', category: 'nichtmetall', row: 3, col: 16, playable: true, electrons: [2, 8, 6], desc: 'Ein zitronengelber, geruchloser Feststoff. Seine organischen Verbindungen riechen oft extrem faulig (z.B. faule Eier). Schwefel ist wichtig für Haare und Proteine.' },
|
||||
{ number: 17, symbol: 'Cl', name: 'Chlor', mass: '35.45 u', category: 'halogen', row: 3, col: 17, playable: true, electrons: [2, 8, 7], desc: 'Ein giftiges, stechend riechendes gelbgrünes Gas. Chlor ist extrem reaktiv und wird weltweit zur Desinfektion von Trinkwasser und Pools genutzt.' },
|
||||
{ number: 18, symbol: 'Ar', name: 'Argon', mass: '39.948 u', category: 'edelgas', row: 3, col: 18, playable: false, electrons: [2, 8, 8], desc: 'Das dritthäufigste Gas in unserer Atmosphäre. Argon wird als ungiftiges Schutzgas beim Schweißen und in Doppelglasscheiben zur Wärmeisolierung eingesetzt.' },
|
||||
{ number: 19, symbol: 'K', name: 'Kalium', mass: '39.098 u', category: 'alkalimetall', row: 4, col: 1, playable: false, electrons: [2, 8, 8, 1], desc: 'Ein weiches, hochreaktives Alkalimetall. Es reagiert noch heftiger mit Wasser als Natrium und ist essenziell für die Weiterleitung von Nervensignalen.' },
|
||||
{ number: 20, symbol: 'Ca', name: 'Calcium', mass: '40.078 u', category: 'erdalkali', row: 4, col: 2, playable: false, electrons: [2, 8, 8, 2], desc: 'Der elementare Baustein für Skelette und Zähne! Calcium bildet Knochen, Eierschalen, Muscheln und Kreide und ist wichtig für die Muskelarbeit.' },
|
||||
{ number: 26, symbol: 'Fe', name: 'Eisen', mass: '55.845 u', category: 'uebergang', row: 4, col: 8, playable: true, electrons: [2, 8, 14, 2], desc: 'Das am häufigsten genutzte Metall der Menschheit. Eisen bildet das Zentrum unseres Erdkerns (Magnetfeld) und transportiert Sauerstoff in unserem Blut (Hämoglobin).' }
|
||||
];
|
||||
|
||||
// Rezepturenbuch (die Formeln müssen genau den Kombinationen der Symbole entsprechen)
|
||||
const recipes = [
|
||||
{
|
||||
@ -158,18 +193,19 @@ const recipes = [
|
||||
ingredients: ['C', 'C', 'H', 'H', 'H', 'H'], // 2x Kohlenstoff, 4x Wasserstoff
|
||||
result: 'C₂H₄ (Ethen)',
|
||||
color: '#ffeaa7',
|
||||
desc: 'Ethen (Ethylen) ist ein gasförmiges Pflanzenhormon, das Früchte reifen lässt. Industriell ist es der absolut wichtigste Baustein zur Herstellung des Kunststoffs Polyethylen (PE).'
|
||||
desc: 'Ethen (Ethylen) is ein gasförmiges Pflanzenhormon, das Früchte reifen lässt. Industriell ist es der absolut wichtigste Baustein zur Herstellung des Kunststoffs Polyethylen (PE).'
|
||||
}
|
||||
];
|
||||
|
||||
// Geladene Entdeckungen aus dem LocalStorage
|
||||
let discoveredMolecules = new Set(JSON.parse(localStorage.getItem('chem_lab_discoveries') || '[]'));
|
||||
let selectedPSEElement = null;
|
||||
|
||||
// Initiales Laden
|
||||
updateStats();
|
||||
renderDiscoveryBook();
|
||||
|
||||
// Button-Klicks registrieren für Spawnen
|
||||
// Button-Klicks registrieren für Spawnen in Sidebar
|
||||
spawnBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const symbol = btn.dataset.element;
|
||||
@ -185,14 +221,45 @@ clearDeskBtn.addEventListener('click', () => {
|
||||
updateStats();
|
||||
});
|
||||
|
||||
// Modal Events
|
||||
// =========================================
|
||||
// MODALS LOGIC
|
||||
// =========================================
|
||||
|
||||
// Info-Modal (Entdeckungen) Schließen
|
||||
modalCloseBtn.addEventListener('click', closeModal);
|
||||
modalOverlay.addEventListener('click', closeModal);
|
||||
modalCloseIcon.addEventListener('click', closeModal);
|
||||
|
||||
function closeModal() {
|
||||
infoModal.classList.add('hidden');
|
||||
}
|
||||
|
||||
// PSE Modal Steuerung
|
||||
pseToggleBtn.addEventListener('click', () => {
|
||||
pseModal.classList.remove('hidden');
|
||||
renderPSEGrid();
|
||||
});
|
||||
|
||||
pseCloseBtn.addEventListener('click', closePSE);
|
||||
pseCloseIcon.addEventListener('click', closePSE);
|
||||
pseOverlay.addEventListener('click', closePSE);
|
||||
|
||||
function closePSE() {
|
||||
pseModal.classList.add('hidden');
|
||||
}
|
||||
|
||||
// PSE Atom Spawnen Event
|
||||
pseSpawnBtn.addEventListener('click', () => {
|
||||
if (selectedPSEElement) {
|
||||
spawnAtom(selectedPSEElement.symbol, elementDetails[selectedPSEElement.symbol].color);
|
||||
closePSE();
|
||||
}
|
||||
});
|
||||
|
||||
// =========================================
|
||||
// GAMEPLAY CORE LOGIC
|
||||
// =========================================
|
||||
|
||||
function spawnAtom(symbol, color) {
|
||||
const el = document.createElement('div');
|
||||
el.classList.add('atom');
|
||||
@ -200,7 +267,7 @@ function spawnAtom(symbol, color) {
|
||||
el.dataset.symbol = symbol;
|
||||
el.style.backgroundColor = color;
|
||||
|
||||
// Farblich angepasster Text für dunkle Elemente
|
||||
// Farblich angepasster Text für dunkle/kontrastreiche Elemente
|
||||
if (symbol === 'C' || symbol === 'Fe') {
|
||||
el.style.color = '#fff';
|
||||
} else {
|
||||
@ -387,7 +454,7 @@ function triggerExplosion(x, y, color) {
|
||||
const angle = Math.random() * Math.PI * 2;
|
||||
const velocity = 40 + Math.random() * 80;
|
||||
const targetX = Math.cos(angle) * velocity;
|
||||
const targetY = Math.sin(angle) * velocity + 20; // Leichte Gravitation (nach unten gezogen)
|
||||
const targetY = Math.sin(angle) * velocity + 20; // Leichte Gravitation
|
||||
|
||||
p.animate([
|
||||
{ transform: 'translate(0, 0) scale(1)', opacity: 1 },
|
||||
@ -405,10 +472,10 @@ function triggerExplosion(x, y, color) {
|
||||
function showModal(recipe, isNew = true) {
|
||||
if (isNew) {
|
||||
modalTitle.innerText = "Molekül entdeckt! 🎉";
|
||||
document.querySelector('.modal-emoji').innerText = "🎉";
|
||||
document.querySelector('#info-modal .modal-emoji').innerText = "🎉";
|
||||
} else {
|
||||
modalTitle.innerText = "Molekül-Lexikon 📖";
|
||||
document.querySelector('.modal-emoji').innerText = "📖";
|
||||
document.querySelector('#info-modal .modal-emoji').innerText = "📖";
|
||||
}
|
||||
|
||||
// Subscripts für Formel schön rendern
|
||||
@ -416,7 +483,7 @@ function showModal(recipe, isNew = true) {
|
||||
modalFormula.innerHTML = prettyFormula;
|
||||
modalFormula.style.backgroundColor = recipe.color;
|
||||
|
||||
// Reiner Name (Text in Klammern aus z.B. "H₂O (Wasser)")
|
||||
// Reiner Name (Text in Klammern)
|
||||
const cleanName = recipe.result.substring(recipe.result.indexOf('(') + 1, recipe.result.indexOf(')'));
|
||||
modalName.innerText = cleanName;
|
||||
|
||||
@ -472,3 +539,132 @@ function updateStats() {
|
||||
atomCountEl.innerText = atoms;
|
||||
moleculeCountEl.innerText = molecules;
|
||||
}
|
||||
|
||||
// =========================================
|
||||
// INTERACTIVE PSE LOGIC
|
||||
// =========================================
|
||||
|
||||
function renderPSEGrid() {
|
||||
const grid = document.getElementById('pse-grid');
|
||||
grid.innerHTML = '';
|
||||
|
||||
pseElements.forEach(el => {
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('pse-el');
|
||||
div.style.gridRow = el.row;
|
||||
div.style.gridColumn = el.col;
|
||||
div.dataset.symbol = el.symbol;
|
||||
|
||||
div.innerHTML = `
|
||||
<span class="pse-el-number">${el.number}</span>
|
||||
<span class="pse-el-symbol">${el.symbol}</span>
|
||||
<span class="pse-el-name">${el.name}</span>
|
||||
`;
|
||||
|
||||
if (el.playable) {
|
||||
div.classList.add('active-el');
|
||||
div.classList.add(el.category);
|
||||
div.addEventListener('click', () => {
|
||||
selectElementSteckbrief(el);
|
||||
});
|
||||
} else {
|
||||
div.classList.add('locked-el');
|
||||
div.addEventListener('click', () => {
|
||||
// Selektiert dekorative Elemente trotzdem für den Steckbrief (Lerneffekt!), aber deaktiviert Spawnen
|
||||
selectElementSteckbrief(el, false);
|
||||
});
|
||||
}
|
||||
grid.appendChild(div);
|
||||
});
|
||||
}
|
||||
|
||||
function selectElementSteckbrief(el, canSpawn = true) {
|
||||
selectedPSEElement = el;
|
||||
|
||||
const emptyDiv = document.querySelector('.steckbrief-empty');
|
||||
const cardDiv = document.querySelector('.steckbrief-card');
|
||||
|
||||
emptyDiv.classList.add('hidden');
|
||||
cardDiv.classList.remove('hidden');
|
||||
|
||||
const box = document.getElementById('steckbrief-box');
|
||||
box.innerText = el.symbol;
|
||||
box.className = ''; // Zurücksetzen
|
||||
box.classList.add('active-el', el.category);
|
||||
|
||||
// Spezieller Textkontrast für dunkle Elemente im Steckbrief
|
||||
if (el.symbol === 'C' || el.symbol === 'Fe') {
|
||||
box.style.color = '#fff';
|
||||
} else {
|
||||
box.style.color = '#333';
|
||||
}
|
||||
|
||||
document.getElementById('steckbrief-name').innerText = el.name;
|
||||
|
||||
// Kategoriennamen lesbar übersetzen
|
||||
const categoryNames = {
|
||||
'nichtmetall': 'Nichtmetall',
|
||||
'edelgas': 'Edelgas',
|
||||
'alkalimetall': 'Alkalimetall',
|
||||
'erdalkali': 'Erdalkalimetall',
|
||||
'uebergang': 'Übergangsmetall',
|
||||
'halogen': 'Halogen',
|
||||
'metalloid': 'Halbmetall',
|
||||
'metall': 'Metall'
|
||||
};
|
||||
document.getElementById('steckbrief-category').innerText = categoryNames[el.category] || el.category;
|
||||
document.getElementById('steckbrief-category').className = ''; // Reset
|
||||
document.getElementById('steckbrief-category').classList.add(el.category);
|
||||
|
||||
document.getElementById('steckbrief-number').innerText = el.number;
|
||||
document.getElementById('steckbrief-mass').innerText = el.mass;
|
||||
document.getElementById('steckbrief-desc').innerText = el.desc;
|
||||
|
||||
// Spawnen-Button steuern
|
||||
if (canSpawn) {
|
||||
pseSpawnBtn.classList.remove('hidden');
|
||||
} else {
|
||||
pseSpawnBtn.classList.add('hidden');
|
||||
}
|
||||
|
||||
// Bohr-Modell Schalen visualisieren
|
||||
renderBohrModel(el.electrons);
|
||||
}
|
||||
|
||||
function renderBohrModel(electronsArray) {
|
||||
const shellsContainer = document.getElementById('bohr-shells');
|
||||
shellsContainer.innerHTML = '';
|
||||
|
||||
electronsArray.forEach((numElectrons, shellIndex) => {
|
||||
const shellDiv = document.createElement('div');
|
||||
shellDiv.classList.add('bohr-shell');
|
||||
|
||||
// Dynamischer Schalendurchmesser basierend auf Schalenindex (Concentric Circles)
|
||||
const diameter = 40 + (shellIndex * 30);
|
||||
shellDiv.style.width = diameter + 'px';
|
||||
shellDiv.style.height = diameter + 'px';
|
||||
|
||||
// Geschwindigkeit variieren für coole Dynamik
|
||||
shellDiv.style.animationDuration = (6 + shellIndex * 4) + 's';
|
||||
|
||||
// Elektronenpunkte auf der Kreisbahn berechnen & platzieren
|
||||
for (let i = 0; i < numElectrons; i++) {
|
||||
const electron = document.createElement('div');
|
||||
electron.classList.add('bohr-electron');
|
||||
|
||||
// Winkel für Gleichverteilung berechnen
|
||||
const angle = (i / numElectrons) * Math.PI * 2;
|
||||
const radius = diameter / 2;
|
||||
const x = Math.cos(angle) * radius;
|
||||
const y = Math.sin(angle) * radius;
|
||||
|
||||
// Auf der CSS-Kreisbahn zentrieren
|
||||
electron.style.left = `calc(50% + ${x}px - 3px)`;
|
||||
electron.style.top = `calc(50% + ${y}px - 3px)`;
|
||||
|
||||
shellDiv.appendChild(electron);
|
||||
}
|
||||
|
||||
shellsContainer.appendChild(shellDiv);
|
||||
});
|
||||
}
|
||||
|
||||
74
index.html
74
index.html
@ -17,9 +17,10 @@
|
||||
<h3>Atome</h3>
|
||||
<div class="elements-grid">
|
||||
<div class="spawn-btn" data-element="H" data-color="#ff7675" title="Wasserstoff">H</div>
|
||||
<div class="spawn-btn" data-element="O" data-color="#74b9ff" title="Sauerstoff">O</div>
|
||||
<div class="spawn-btn" data-element="He" data-color="#e84393" title="Helium">He</div>
|
||||
<div class="spawn-btn" data-element="C" data-color="#2d3436" title="Kohlenstoff">C</div>
|
||||
<div class="spawn-btn" data-element="N" data-color="#a29bfe" title="Stickstoff">N</div>
|
||||
<div class="spawn-btn" data-element="O" data-color="#74b9ff" title="Sauerstoff">O</div>
|
||||
<div class="spawn-btn" data-element="Na" data-color="#ffeaa7" title="Natrium">Na</div>
|
||||
<div class="spawn-btn" data-element="Cl" data-color="#55efc4" title="Chlor">Cl</div>
|
||||
<div class="spawn-btn" data-element="S" data-color="#fdcb6e" title="Schwefel">S</div>
|
||||
@ -48,7 +49,8 @@
|
||||
<div id="stats">
|
||||
Atome: <span id="atom-count">0</span> | Moleküle: <span id="molecule-count">0</span>
|
||||
</div>
|
||||
<button id="clear-desk-btn">🧹 Tisch leeren</button>
|
||||
<button id="pse-toggle-btn" class="control-btn">📊 Periodensystem</button>
|
||||
<button id="clear-desk-btn" class="control-btn danger">🧹 Tisch leeren</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="workspace"></div>
|
||||
@ -61,6 +63,7 @@
|
||||
<div class="modal-header">
|
||||
<span class="modal-emoji">🎉</span>
|
||||
<h2 id="modal-title">Molekül entdeckt!</h2>
|
||||
<button class="modal-close-icon">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="modal-formula-badge">H₂O</div>
|
||||
@ -73,6 +76,73 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- INTERAKTIVES PERIODENSYSTEM (PSE) MODAL -->
|
||||
<div id="pse-modal" class="modal hidden">
|
||||
<div class="modal-overlay"></div>
|
||||
<div class="modal-content pse-modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="modal-emoji">📊</span>
|
||||
<h2>Interaktives Periodensystem (PSE)</h2>
|
||||
<button id="pse-close-icon" class="modal-close-icon">×</button>
|
||||
</div>
|
||||
<div class="pse-modal-body">
|
||||
<!-- Linke Spalte: Das Gitter-System des Periodensystems -->
|
||||
<div class="pse-grid-container">
|
||||
<div id="pse-grid">
|
||||
<!-- Dynamisch befüllt durch app.js -->
|
||||
</div>
|
||||
<div class="pse-legend">
|
||||
<span class="legend-item"><span class="legend-color alkalimetall"></span>Alkalimetalle</span>
|
||||
<span class="legend-item"><span class="legend-color erdalkali"></span>Erdalkali</span>
|
||||
<span class="legend-item"><span class="legend-color uebergang"></span>Übergangsmetalle</span>
|
||||
<span class="legend-item"><span class="legend-color metalloid"></span>Halbmetalle</span>
|
||||
<span class="legend-item"><span class="legend-color nichtmetall"></span>Nichtmetalle</span>
|
||||
<span class="legend-item"><span class="legend-color halogen"></span>Halogene</span>
|
||||
<span class="legend-item"><span class="legend-color edelgas"></span>Edelgase</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rechte Spalte: Der Element-Steckbrief -->
|
||||
<div id="pse-steckbrief">
|
||||
<div class="steckbrief-empty">
|
||||
<p>Klicke auf ein leuchtendes Element im Periodensystem, um den wissenschaftlichen Steckbrief zu öffnen!</p>
|
||||
</div>
|
||||
<div class="steckbrief-card hidden">
|
||||
<div class="steckbrief-header">
|
||||
<div id="steckbrief-box">H</div>
|
||||
<div>
|
||||
<h3 id="steckbrief-name">Wasserstoff</h3>
|
||||
<span id="steckbrief-category">Nichtmetall</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="steckbrief-stats">
|
||||
<div class="steckbrief-stat-box">
|
||||
<span class="stat-label">Ordnungszahl</span>
|
||||
<span id="steckbrief-number" class="stat-value">1</span>
|
||||
</div>
|
||||
<div class="steckbrief-stat-box">
|
||||
<span class="stat-label">Atommasse</span>
|
||||
<span id="steckbrief-mass" class="stat-value">1.008 u</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Bohr-Modell Visualisierung (CSS-Basiert) -->
|
||||
<div class="bohr-model-container">
|
||||
<div class="bohr-nucleus"></div>
|
||||
<div id="bohr-shells">
|
||||
<!-- Shells und Elektronen werden per JS gerendert -->
|
||||
</div>
|
||||
</div>
|
||||
<p id="steckbrief-desc">Das häufigste und leichteste Element im Universum. Es bildet den Brennstoff von Sternen.</p>
|
||||
<button id="pse-spawn-btn">⚛️ Atom auf Tisch spawnen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="pse-close-btn">Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
370
style.css
370
style.css
@ -8,6 +8,15 @@
|
||||
--primary: #3498db;
|
||||
--primary-hover: #2980b9;
|
||||
--shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||
|
||||
/* PSE Category Colors */
|
||||
--color-alkalimetall: #ff7675;
|
||||
--color-erdalkali: #e17055;
|
||||
--color-uebergang: #b2bec3;
|
||||
--color-metalloid: #fdcb6e;
|
||||
--color-nichtmetall: #74b9ff;
|
||||
--color-halogen: #55efc4;
|
||||
--color-edelgas: #e84393;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -89,7 +98,6 @@ body {
|
||||
transition: transform 0.1s, box-shadow 0.1s;
|
||||
}
|
||||
|
||||
/* Element Colors defined in JS, but base defaults for fallback */
|
||||
.spawn-btn:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 6px 10px rgba(0,0,0,0.3);
|
||||
@ -99,7 +107,6 @@ body {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Specific button text colors */
|
||||
.spawn-btn[data-element="C"] {
|
||||
color: #fff;
|
||||
}
|
||||
@ -137,7 +144,6 @@ body {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
/* Scrollbar styles */
|
||||
#discovery-book::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
@ -217,7 +223,7 @@ body {
|
||||
.desk-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
#stats {
|
||||
@ -229,9 +235,7 @@ body {
|
||||
border: 1px solid rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
#clear-desk-btn {
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
.control-btn {
|
||||
border: none;
|
||||
padding: 8px 15px;
|
||||
border-radius: 6px;
|
||||
@ -239,13 +243,26 @@ body {
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
transition: background-color 0.2s, transform 0.1s;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
#clear-desk-btn:hover {
|
||||
#pse-toggle-btn {
|
||||
background-color: #0984e3;
|
||||
color: white;
|
||||
}
|
||||
#pse-toggle-btn:hover {
|
||||
background-color: #00cec9;
|
||||
}
|
||||
|
||||
.control-btn.danger {
|
||||
background-color: #e74c3c;
|
||||
color: white;
|
||||
}
|
||||
.control-btn.danger:hover {
|
||||
background-color: #c0392b;
|
||||
}
|
||||
|
||||
#clear-desk-btn:active {
|
||||
.control-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
@ -375,16 +392,31 @@ body {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.modal-close-icon {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
font-size: 1.8rem;
|
||||
cursor: pointer;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.modal-close-icon:hover {
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.modal-emoji {
|
||||
font-size: 2rem;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.modal-header h2 {
|
||||
font-size: 1.3rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
@ -446,3 +478,321 @@ body {
|
||||
#modal-close-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* ========================================= */
|
||||
/* INTERAKTIVES PERIODENSYSTEM (PSE) STYLES */
|
||||
/* ========================================= */
|
||||
|
||||
.pse-modal-content {
|
||||
width: 1100px;
|
||||
max-width: 95%;
|
||||
height: 650px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.pse-modal-body {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
padding: 20px;
|
||||
gap: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Linke Spalte - PSE Gitter */
|
||||
.pse-grid-container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#pse-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(18, 1fr);
|
||||
grid-template-rows: repeat(4, 1fr);
|
||||
gap: 6px;
|
||||
padding: 10px;
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
border-radius: 12px;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* Einzelnes Element-Kästchen im PSE */
|
||||
.pse-el {
|
||||
aspect-ratio: 1;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 4px;
|
||||
font-size: 0.65rem;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.pse-el.active-el {
|
||||
cursor: pointer;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.pse-el.active-el:hover {
|
||||
transform: scale(1.15);
|
||||
z-index: 10;
|
||||
box-shadow: 0 5px 15px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.pse-el.locked-el {
|
||||
opacity: 0.15;
|
||||
background-color: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
.pse-el.locked-el:hover {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.pse-el-number {
|
||||
font-size: 0.55rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pse-el-symbol {
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.pse-el-name {
|
||||
font-size: 0.5rem;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.pse-el.active-el .pse-el-name,
|
||||
.pse-el.active-el .pse-el-number {
|
||||
color: #333;
|
||||
}
|
||||
.pse-el.active-el[data-symbol="C"] .pse-el-name,
|
||||
.pse-el.active-el[data-symbol="C"] .pse-el-number {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Category Color Highlights for active elements */
|
||||
.alkalimetall { background-color: var(--color-alkalimetall); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
.erdalkali { background-color: var(--color-erdalkali); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
.uebergang { background-color: var(--color-uebergang); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
.metalloid { background-color: var(--color-metalloid); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
.nichtmetall { background-color: var(--color-nichtmetall); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
.halogen { background-color: var(--color-halogen); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
.edelgas { background-color: var(--color-edelgas); color: #333; border-color: rgba(0,0,0,0.15); }
|
||||
|
||||
.pse-el.active-el[data-symbol="C"] {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Legend */
|
||||
.pse-legend {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 15px;
|
||||
padding: 10px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.legend-color {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Rechte Spalte: Steckbrief */
|
||||
#pse-steckbrief {
|
||||
width: 320px;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.steckbrief-empty {
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.steckbrief-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.steckbrief-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
#steckbrief-box {
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
font-size: 1.6rem;
|
||||
color: #333;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
#steckbrief-name {
|
||||
font-size: 1.25rem;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#steckbrief-category {
|
||||
font-size: 0.75rem;
|
||||
color: #ffeaa7;
|
||||
background-color: rgba(255, 234, 167, 0.1);
|
||||
padding: 2px 8px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(255, 234, 167, 0.2);
|
||||
}
|
||||
|
||||
.steckbrief-stats {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.steckbrief-stat-box {
|
||||
flex: 1;
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.65rem;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
display: block;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#steckbrief-desc {
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.4;
|
||||
color: #dfe6e9;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#pse-spawn-btn {
|
||||
background-color: #2ed573;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
font-size: 0.95rem;
|
||||
transition: background-color 0.2s, transform 0.1s;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.2);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#pse-spawn-btn:hover {
|
||||
background-color: #26af5a;
|
||||
}
|
||||
|
||||
#pse-spawn-btn:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* Bohr Model (Atomschalen-Visualisierung) */
|
||||
.bohr-model-container {
|
||||
height: 140px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.03);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bohr-nucleus {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background-color: #ff7675;
|
||||
position: absolute;
|
||||
box-shadow: 0 0 10px #ff7675;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.bohr-shell {
|
||||
position: absolute;
|
||||
border: 1px dashed rgba(255,255,255,0.15);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
animation: rotate-shell 20s linear infinite;
|
||||
}
|
||||
|
||||
.bohr-shell:nth-child(1) { width: 50px; height: 50px; animation-duration: 8s; }
|
||||
.bohr-shell:nth-child(2) { width: 90px; height: 90px; animation-duration: 15s; }
|
||||
.bohr-shell:nth-child(3) { width: 130px; height: 130px; animation-duration: 25s; }
|
||||
|
||||
.bohr-electron {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: #54a0ff;
|
||||
position: absolute;
|
||||
box-shadow: 0 0 5px #54a0ff;
|
||||
}
|
||||
|
||||
@keyframes rotate-shell {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user