Compare commits

...

3 Commits

4 changed files with 1263 additions and 1743 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3,404 +3,239 @@
* Verbessert die Interaktion mit der Mindmap und steuert die Seitenleisten-Anzeige
*/
// Stellt sicher, dass das Dokument geladen ist, bevor Aktionen ausgeführt werden
document.addEventListener('DOMContentLoaded', function() {
console.log('Mindmap-Interaktionsverbesserungen werden initialisiert...');
// Auf das Laden der Mindmap warten
document.addEventListener('mindmap-loaded', setupInteractionEnhancements);
// Sofortiges Setup für statische Interaktionen
setupStaticInteractions();
// Globale Variablen
let cy;
let selectedNode = null;
let isLegendVisible = true;
// Direkten Event-Listener für Knotenauswahl einrichten
setupNodeSelectionListener();
// Initialisierung der Mindmap
document.addEventListener('DOMContentLoaded', function() {
// Cytoscape-Container initialisieren
cy = cytoscape({
container: document.getElementById('cy'),
style: [
{
selector: 'node',
style: {
'background-color': '#60a5fa',
'label': 'data(label)',
'text-valign': 'center',
'text-halign': 'center',
'text-wrap': 'wrap',
'text-max-width': '100px',
'font-size': '12px',
'color': '#fff',
'text-outline-color': '#000',
'text-outline-width': '2px',
'width': '40px',
'height': '40px',
'border-width': '2px',
'border-color': '#fff',
'border-opacity': '0.5',
'padding': '10px',
'text-events': 'yes'
}
},
{
selector: 'edge',
style: {
'width': '2px',
'line-color': 'rgba(255, 255, 255, 0.3)',
'target-arrow-color': 'rgba(255, 255, 255, 0.3)',
'target-arrow-shape': 'triangle',
'curve-style': 'bezier',
'label': 'data(label)',
'font-size': '10px',
'color': '#fff',
'text-outline-color': '#000',
'text-outline-width': '2px',
'text-rotation': 'autorotate'
}
},
{
selector: ':selected',
style: {
'background-color': '#8b5cf6',
'line-color': '#8b5cf6',
'target-arrow-color': '#8b5cf6',
'source-arrow-color': '#8b5cf6',
'text-outline-color': '#000',
'text-outline-width': '2px',
'border-width': '3px',
'border-color': '#fff',
'border-opacity': '1'
}
},
{
selector: '.highlighted',
style: {
'background-color': '#10b981',
'line-color': '#10b981',
'target-arrow-color': '#10b981',
'source-arrow-color': '#10b981',
'transition-property': 'background-color, line-color, target-arrow-color',
'transition-duration': '0.3s'
}
}
],
layout: {
name: 'cose',
idealEdgeLength: 100,
nodeOverlap: 20,
refresh: 20,
fit: true,
padding: 30,
randomize: false,
componentSpacing: 100,
nodeRepulsion: 400000,
edgeElasticity: 100,
nestingFactor: 5,
gravity: 80,
numIter: 1000,
initialTemp: 200,
coolingFactor: 0.95,
minTemp: 1.0
}
});
// Event-Listener für Knoten
cy.on('tap', 'node', function(evt) {
const node = evt.target;
updateNodeInfo(node);
highlightConnectedNodes(node);
});
// Event-Listener für Hintergrund-Klick
cy.on('tap', function(evt) {
if (evt.target === cy) {
resetHighlighting();
hideNodeInfo();
}
});
// Zoom-Kontrollen
document.getElementById('zoom-in').addEventListener('click', function() {
cy.zoom({
level: cy.zoom() * 1.2,
renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 }
});
});
document.getElementById('zoom-out').addEventListener('click', function() {
cy.zoom({
level: cy.zoom() / 1.2,
renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 }
});
});
document.getElementById('reset-view').addEventListener('click', function() {
cy.fit();
});
// Legende ein-/ausblenden
document.getElementById('toggle-legend').addEventListener('click', function() {
const legend = document.querySelector('.category-legend');
isLegendVisible = !isLegendVisible;
legend.style.display = isLegendVisible ? 'flex' : 'none';
});
// Tastatursteuerung
document.addEventListener('keydown', function(evt) {
switch(evt.key) {
case '+':
cy.zoom({
level: cy.zoom() * 1.2,
renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 }
});
break;
case '-':
cy.zoom({
level: cy.zoom() / 1.2,
renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 }
});
break;
case 'Escape':
resetHighlighting();
hideNodeInfo();
break;
}
});
});
// Richtet grundlegende statische Interaktionen ein
function setupStaticInteractions() {
// Vergrößert die Mindmap auf Vollbildmodus, wenn der entsprechende Button geklickt wird
const fullscreenBtn = document.getElementById('fullscreen-btn');
if (fullscreenBtn) {
fullscreenBtn.addEventListener('click', toggleFullscreen);
// Knoteninformationen aktualisieren
function updateNodeInfo(node) {
const infoPanel = document.getElementById('node-info');
const infoContent = infoPanel.querySelector('.info-content');
// Knotendaten abrufen
const nodeData = node.data();
// Info-Panel aktualisieren
infoContent.innerHTML = `
<h4 class="text-lg font-semibold mb-2">${nodeData.label}</h4>
<p class="mb-3">${nodeData.description || 'Keine Beschreibung verfügbar.'}</p>
<div class="mt-4">
<h5 class="text-sm font-semibold mb-2">Verknüpfte Konzepte:</h5>
<ul class="space-y-1">
${getConnectedNodesList(node)}
</ul>
</div>
`;
// Panel anzeigen
infoPanel.classList.add('visible');
}
// Verbundene Knoten hervorheben
function highlightConnectedNodes(node) {
// Vorherige Hervorhebungen zurücksetzen
resetHighlighting();
// Ausgewählten Knoten hervorheben
node.addClass('highlighted');
// Verbundene Knoten und Kanten hervorheben
const connectedElements = node.neighborhood();
connectedElements.addClass('highlighted');
}
// Hervorhebungen zurücksetzen
function resetHighlighting() {
cy.elements().removeClass('highlighted');
}
// Info-Panel ausblenden
function hideNodeInfo() {
const infoPanel = document.getElementById('node-info');
infoPanel.classList.remove('visible');
}
// Liste der verbundenen Knoten generieren
function getConnectedNodesList(node) {
const connectedNodes = node.neighborhood('node');
if (connectedNodes.length === 0) {
return '<li class="text-gray-400">Keine direkten Verbindungen</li>';
}
// Initialisiert die Hover-Effekte für die Seitenleisten-Panels
initializePanelEffects();
return connectedNodes.map(connectedNode => {
const data = connectedNode.data();
return `
<li class="flex items-center space-x-2">
<span class="w-2 h-2 rounded-full" style="background-color: ${getNodeColor(data.category)}"></span>
<span>${data.label}</span>
</li>
`;
}).join('');
}
// Richtet erweiterte Interaktionen mit der geladenen Mindmap ein
function setupInteractionEnhancements() {
console.log('Mindmap geladen - verbesserte Interaktionen werden eingerichtet');
// Zugriff auf die Mindmap-Instanz
const mindmap = window.mindmapInstance;
if (!mindmap) {
console.warn('Mindmap-Instanz nicht gefunden!');
return;
}
// Verbesserte Zoom-Kontrollen
setupZoomControls(mindmap);
// Verhindere, dass der Browser die Seite scrollt, wenn über der Mindmap gezoomt wird
preventScrollWhileZooming();
// Tastaturkürzel für Mindmap-Interaktionen
setupKeyboardShortcuts(mindmap);
// Verbesserte Touch-Gesten für mobile Geräte
setupTouchInteractions(mindmap);
}
// Verhindert Browser-Scrolling während Zoom in der Mindmap
function preventScrollWhileZooming() {
const cyContainer = document.getElementById('cy');
if (cyContainer) {
cyContainer.addEventListener('wheel', function(e) {
if (e.ctrlKey || e.metaKey) {
e.preventDefault(); // Verhindert Browser-Zoom bei Ctrl+Wheel
}
}, { passive: false });
}
}
// Richtet verbesserte Zoom-Kontrollen ein
function setupZoomControls(mindmap) {
const zoomInBtn = document.getElementById('zoom-in-btn');
const zoomOutBtn = document.getElementById('zoom-out-btn');
const resetZoomBtn = document.getElementById('reset-btn');
if (zoomInBtn) {
zoomInBtn.addEventListener('click', function() {
mindmap.svg.transition()
.duration(300)
.call(mindmap.svg.zoom().scaleBy, 1.4);
});
}
if (zoomOutBtn) {
zoomOutBtn.addEventListener('click', function() {
mindmap.svg.transition()
.duration(300)
.call(mindmap.svg.zoom().scaleBy, 0.7);
});
}
if (resetZoomBtn) {
resetZoomBtn.addEventListener('click', function() {
mindmap.svg.transition()
.duration(500)
.call(mindmap.svg.zoom().transform, d3.zoomIdentity);
});
}
}
// Vollbildmodus umschalten
function toggleFullscreen() {
const mindmapContainer = document.querySelector('.mindmap-container');
if (!mindmapContainer) return;
if (!document.fullscreenElement) {
// Vollbildmodus aktivieren
if (mindmapContainer.requestFullscreen) {
mindmapContainer.requestFullscreen();
} else if (mindmapContainer.mozRequestFullScreen) {
mindmapContainer.mozRequestFullScreen();
} else if (mindmapContainer.webkitRequestFullscreen) {
mindmapContainer.webkitRequestFullscreen();
} else if (mindmapContainer.msRequestFullscreen) {
mindmapContainer.msRequestFullscreen();
}
// Icon ändern
const fullscreenBtn = document.getElementById('fullscreen-btn');
if (fullscreenBtn) {
const icon = fullscreenBtn.querySelector('i');
if (icon) {
icon.className = 'fa-solid fa-compress';
}
fullscreenBtn.setAttribute('title', 'Vollbildmodus beenden');
}
} else {
// Vollbildmodus beenden
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
// Icon zurücksetzen
const fullscreenBtn = document.getElementById('fullscreen-btn');
if (fullscreenBtn) {
const icon = fullscreenBtn.querySelector('i');
if (icon) {
icon.className = 'fa-solid fa-expand';
}
fullscreenBtn.setAttribute('title', 'Vollbildmodus');
}
}
}
// Initialisiert Effekte für Seitenleisten-Panels
function initializePanelEffects() {
// Selektiert alle Panel-Elemente
const panels = document.querySelectorAll('[data-sidebar]');
panels.forEach(panel => {
// Hover-Effekt für Panels
panel.addEventListener('mouseenter', function() {
this.classList.add('hover');
});
panel.addEventListener('mouseleave', function() {
this.classList.remove('hover');
});
});
}
// Richtet Tastaturkürzel für Mindmap-Interaktionen ein
function setupKeyboardShortcuts(mindmap) {
document.addEventListener('keydown', function(e) {
// Nur fortfahren, wenn keine Texteingabe im Fokus ist
if (document.activeElement.tagName === 'INPUT' ||
document.activeElement.tagName === 'TEXTAREA' ||
document.activeElement.isContentEditable) {
return;
}
// Tastaturkürzel
switch(e.key) {
case '+':
case '=':
// Einzoomen
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
mindmap.svg.transition()
.duration(300)
.call(mindmap.svg.zoom().scaleBy, 1.2);
}
break;
case '-':
// Auszoomen
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
mindmap.svg.transition()
.duration(300)
.call(mindmap.svg.zoom().scaleBy, 0.8);
}
break;
case '0':
// Zoom zurücksetzen
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
mindmap.svg.transition()
.duration(500)
.call(mindmap.svg.zoom().transform, d3.zoomIdentity);
}
break;
case 'f':
// Vollbildmodus umschalten
if (e.ctrlKey || e.metaKey) {
e.preventDefault();
toggleFullscreen();
}
break;
case 'Escape':
// Ausgewählten Knoten abwählen
if (mindmap.selectedNode) {
mindmap.nodeClicked(null, mindmap.selectedNode);
}
break;
}
});
}
// Richtet Touch-Gesten für mobile Geräte ein
function setupTouchInteractions(mindmap) {
const cyContainer = document.getElementById('cy');
if (!cyContainer) return;
let touchStartX, touchStartY;
let touchStartTime;
// Touch-Start-Event
cyContainer.addEventListener('touchstart', function(e) {
if (e.touches.length === 1) {
touchStartX = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
touchStartTime = Date.now();
}
});
// Touch-End-Event für Doppeltipp-Erkennung
cyContainer.addEventListener('touchend', function(e) {
if (Date.now() - touchStartTime < 300) { // Kurzer Tipp
const doubleTapDelay = 300;
const now = Date.now();
if (now - (window.lastTapTime || 0) < doubleTapDelay) {
// Doppeltipp erkannt - Zentriere Ansicht
mindmap.svg.transition()
.duration(500)
.call(mindmap.svg.zoom().transform, d3.zoomIdentity);
e.preventDefault();
}
window.lastTapTime = now;
}
});
}
// Richtet einen Event-Listener für die Knotenauswahl ein
function setupNodeSelectionListener() {
document.addEventListener('mindmap-node-selected', function(event) {
const node = event.detail;
if (node) {
console.log('Knoten ausgewählt:', node);
showNodeDescriptionSidebar(node);
}
});
document.addEventListener('mindmap-node-deselected', function() {
console.log('Knoten abgewählt');
showDefaultSidebar();
});
}
// Zeigt die Standard-Seitenleiste an
function showDefaultSidebar() {
// Finde die Seitenleistenelemente
const aboutMindmapPanel = document.querySelector('[data-sidebar="about-mindmap"]');
const categoriesPanel = document.querySelector('[data-sidebar="categories"]');
const nodeDescriptionPanel = document.querySelector('[data-sidebar="node-description"]');
if (aboutMindmapPanel && categoriesPanel && nodeDescriptionPanel) {
// Beschreibungspanel ausblenden
nodeDescriptionPanel.style.display = 'none';
// Standardpanels einblenden mit Animation
aboutMindmapPanel.style.display = 'block';
categoriesPanel.style.display = 'block';
setTimeout(() => {
aboutMindmapPanel.style.opacity = '1';
aboutMindmapPanel.style.transform = 'translateY(0)';
categoriesPanel.style.opacity = '1';
categoriesPanel.style.transform = 'translateY(0)';
}, 50);
}
}
// Zeigt die Knotenbeschreibung in der Seitenleiste an
function showNodeDescriptionSidebar(node) {
// Finde die Seitenleistenelemente
const aboutMindmapPanel = document.querySelector('[data-sidebar="about-mindmap"]');
const categoriesPanel = document.querySelector('[data-sidebar="categories"]');
const nodeDescriptionPanel = document.querySelector('[data-sidebar="node-description"]');
if (aboutMindmapPanel && categoriesPanel && nodeDescriptionPanel) {
// Standardpanels ausblenden
aboutMindmapPanel.style.transition = 'all 0.3s ease';
categoriesPanel.style.transition = 'all 0.3s ease';
aboutMindmapPanel.style.opacity = '0';
aboutMindmapPanel.style.transform = 'translateY(10px)';
categoriesPanel.style.opacity = '0';
categoriesPanel.style.transform = 'translateY(10px)';
setTimeout(() => {
aboutMindmapPanel.style.display = 'none';
categoriesPanel.style.display = 'none';
// Beschreibungspanel vorbereiten
const titleElement = nodeDescriptionPanel.querySelector('[data-node-title]');
const descriptionElement = nodeDescriptionPanel.querySelector('[data-node-description]');
if (titleElement && descriptionElement) {
titleElement.textContent = node.name || 'Unbenannter Knoten';
// Beschreibung setzen oder Standardbeschreibung generieren
let description = node.description;
if (!description || description.trim() === '') {
description = generateNodeDescription(node);
}
descriptionElement.textContent = description;
}
// Beschreibungspanel einblenden mit Animation
nodeDescriptionPanel.style.display = 'block';
nodeDescriptionPanel.style.opacity = '0';
nodeDescriptionPanel.style.transform = 'translateY(10px)';
setTimeout(() => {
nodeDescriptionPanel.style.transition = 'all 0.4s ease';
nodeDescriptionPanel.style.opacity = '1';
nodeDescriptionPanel.style.transform = 'translateY(0)';
}, 50);
}, 300);
}
}
// Generiert automatisch eine Beschreibung für einen Knoten ohne Beschreibung
function generateNodeDescription(node) {
const descriptions = {
"Wissen": "Der zentrale Knotenpunkt der Mindmap, der alle wissenschaftlichen Disziplinen und Wissensgebiete verbindet. Hier finden sich grundlegende Erkenntnisse und Verbindungen zu spezifischeren Fachgebieten.",
"Quantenphysik": "Ein Zweig der Physik, der sich mit dem Verhalten und den Interaktionen von Materie und Energie auf der kleinsten Skala beschäftigt. Quantenmechanische Phänomene wie Superposition und Verschränkung bilden die Grundlage für moderne Technologien wie Quantencomputer und -kommunikation.",
"Neurowissenschaften": "Interdisziplinäres Forschungsgebiet, das die Struktur, Funktion und Entwicklung des Nervensystems und des Gehirns untersucht. Die Erkenntnisse beeinflussen unser Verständnis von Bewusstsein, Kognition, Verhalten und neurologischen Erkrankungen.",
"Künstliche Intelligenz": "Forschungsgebiet der Informatik, das sich mit der Entwicklung von Systemen befasst, die menschliche Intelligenzformen simulieren können. KI umfasst maschinelles Lernen, neuronale Netze und verschiedene Ansätze zur Problemlösung und Mustererkennung.",
"Klimaforschung": "Wissenschaftliche Disziplin, die sich mit der Untersuchung des Erdklimas, seinen Veränderungen und den zugrundeliegenden physikalischen Prozessen beschäftigt. Sie liefert wichtige Erkenntnisse zu Klimawandel, Wettermuster und globalen Umweltveränderungen.",
"Genetik": "Wissenschaft der Gene, Vererbung und der Variation von Organismen. Moderne genetische Forschung umfasst Genomik, Gentechnologie und das Verständnis der molekularen Grundlagen des Lebens sowie ihrer Anwendungen in Medizin und Biotechnologie.",
"Astrophysik": "Zweig der Astronomie, der die physikalischen Eigenschaften und Prozesse von Himmelskörpern und des Universums untersucht. Sie erforscht Phänomene wie Schwarze Löcher, Galaxien, kosmische Strahlung und die Entstehung und Entwicklung des Universums.",
"Philosophie": "Disziplin, die sich mit fundamentalen Fragen des Wissens, der Realität und der Existenz auseinandersetzt. Sie umfasst Bereiche wie Metaphysik, Erkenntnistheorie, Ethik und Logik und bildet die Grundlage für kritisches Denken und wissenschaftliche Methodik.",
"Wissenschaft": "Systematische Erforschung der Natur und der materiellen Welt durch Beobachtung, Experimente und die Formulierung überprüfbarer Theorien. Sie umfasst Naturwissenschaften, Sozialwissenschaften und angewandte Wissenschaften.",
"Technologie": "Anwendung wissenschaftlicher Erkenntnisse für praktische Zwecke. Sie umfasst die Entwicklung von Werkzeugen, Maschinen, Materialien und Prozessen zur Lösung von Problemen und zur Verbesserung der menschlichen Lebensbedingungen.",
"Künste": "Ausdruck menschlicher Kreativität und Imagination in verschiedenen Formen wie Malerei, Musik, Literatur, Theater und Film. Die Künste erforschen ästhetische, emotionale und intellektuelle Dimensionen der menschlichen Erfahrung.",
"Biologie": "Wissenschaft des Lebens und der lebenden Organismen. Sie umfasst Bereiche wie Molekularbiologie, Evolutionsbiologie, Ökologie und beschäftigt sich mit der Struktur, Funktion, Entwicklung und Evolution lebender Systeme.",
"Mathematik": "Wissenschaft der Muster, Strukturen und Beziehungen. Sie ist die Sprache der Naturwissenschaften und bildet die Grundlage für quantitative Analysen, logisches Denken und Problemlösung in allen wissenschaftlichen Disziplinen.",
"Psychologie": "Wissenschaftliche Untersuchung des menschlichen Verhaltens und der mentalen Prozesse. Sie erforscht Bereiche wie Kognition, Emotion, Persönlichkeit, soziale Interaktionen und die Behandlung psychischer Störungen.",
"Ethik": "Teilgebiet der Philosophie, das sich mit moralischen Prinzipien, Werten und der Frage nach richtigem und falschem Handeln beschäftigt. Sie bildet die Grundlage für moralische Entscheidungsfindung in allen Lebensbereichen."
// Farbe basierend auf Kategorie
function getNodeColor(category) {
const colors = {
'Philosophie': '#60a5fa',
'Wissenschaft': '#8b5cf6',
'Technologie': '#10b981',
'Künste': '#f59e0b',
'Psychologie': '#ef4444'
};
// Verwende vordefinierte Beschreibung, wenn verfügbar
if (node.name && descriptions[node.name]) {
return descriptions[node.name];
}
// Generische Beschreibung basierend auf dem Knotentyp
switch (node.type) {
case 'category':
return `Dieser Knoten repräsentiert die Kategorie "${node.name}", die verschiedene verwandte Konzepte und Ideen zusammenfasst. Wählen Sie einen der verbundenen Unterthemen, um mehr Details zu erfahren.`;
case 'subcategory':
return `"${node.name}" ist eine Unterkategorie, die spezifische Aspekte eines größeren Themenbereichs beleuchtet. Die verbundenen Knoten zeigen wichtige Konzepte und Ideen innerhalb dieses Bereichs.`;
default:
return `Dieser Knoten repräsentiert das Konzept "${node.name}". Erforschen Sie die verbundenen Knoten, um Zusammenhänge und verwandte Ideen zu entdecken.`;
}
return colors[category] || '#60a5fa';
}

View File

@@ -1,7 +1,7 @@
/**
* Update Mindmap
* Dieses Skript fügt die neuen wissenschaftlichen Knoten zur Mindmap hinzu
* und stellt sicher, dass sie korrekt angezeigt werden.
* Dieses Skript fügt Knoten zur Mindmap hinzu und stellt sicher,
* dass sie im neuronalen Netzwerk-Design angezeigt werden.
*/
// Warte bis DOM geladen ist
@@ -16,13 +16,203 @@ document.addEventListener('DOMContentLoaded', function() {
// Auf das Laden der Mindmap warten
document.addEventListener('mindmap-loaded', function() {
console.log('Mindmap geladen, füge wissenschaftliche Knoten hinzu...');
enhanceMindmap();
console.log('Mindmap geladen, wende neuronales Netzwerk-Design an...');
updateMindmap();
});
});
// Mindmap-Daten
const mindmapData = {
nodes: [
// Philosophie
{
id: 'philosophy',
label: 'Philosophie',
category: 'Philosophie',
description: 'Die Lehre vom Denken und der Erkenntnis'
},
{
id: 'epistemology',
label: 'Erkenntnistheorie',
category: 'Philosophie',
description: 'Untersuchung der Natur und Grenzen menschlicher Erkenntnis'
},
{
id: 'ethics',
label: 'Ethik',
category: 'Philosophie',
description: 'Lehre vom moralisch richtigen Handeln'
},
// Wissenschaft
{
id: 'science',
label: 'Wissenschaft',
category: 'Wissenschaft',
description: 'Systematische Erforschung der Natur und Gesellschaft'
},
{
id: 'physics',
label: 'Physik',
category: 'Wissenschaft',
description: 'Lehre von der Materie und ihren Wechselwirkungen'
},
{
id: 'biology',
label: 'Biologie',
category: 'Wissenschaft',
description: 'Lehre von den Lebewesen und ihren Lebensprozessen'
},
// Technologie
{
id: 'technology',
label: 'Technologie',
category: 'Technologie',
description: 'Anwendung wissenschaftlicher Erkenntnisse'
},
{
id: 'ai',
label: 'Künstliche Intelligenz',
category: 'Technologie',
description: 'Maschinelles Lernen und intelligente Systeme'
},
{
id: 'robotics',
label: 'Robotik',
category: 'Technologie',
description: 'Entwicklung und Steuerung von Robotern'
},
// Künste
{
id: 'arts',
label: 'Künste',
category: 'Künste',
description: 'Kreativer Ausdruck und künstlerische Gestaltung'
},
{
id: 'music',
label: 'Musik',
category: 'Künste',
description: 'Kunst der Töne und Klänge'
},
{
id: 'literature',
label: 'Literatur',
category: 'Künste',
description: 'Schriftliche Werke und Dichtkunst'
},
// Psychologie
{
id: 'psychology',
label: 'Psychologie',
category: 'Psychologie',
description: 'Wissenschaft vom Erleben und Verhalten'
},
{
id: 'cognitive',
label: 'Kognitive Psychologie',
category: 'Psychologie',
description: 'Studium mentaler Prozesse'
},
{
id: 'behavioral',
label: 'Verhaltenspsychologie',
category: 'Psychologie',
description: 'Analyse von Verhaltensmustern'
}
],
edges: [
// Philosophie-Verbindungen
{ source: 'philosophy', target: 'epistemology', label: 'umfasst' },
{ source: 'philosophy', target: 'ethics', label: 'umfasst' },
{ source: 'philosophy', target: 'science', label: 'beeinflusst' },
// Wissenschaft-Verbindungen
{ source: 'science', target: 'physics', label: 'umfasst' },
{ source: 'science', target: 'biology', label: 'umfasst' },
{ source: 'science', target: 'technology', label: 'fördert' },
// Technologie-Verbindungen
{ source: 'technology', target: 'ai', label: 'umfasst' },
{ source: 'technology', target: 'robotics', label: 'umfasst' },
{ source: 'ai', target: 'cognitive', label: 'beeinflusst' },
// Künste-Verbindungen
{ source: 'arts', target: 'music', label: 'umfasst' },
{ source: 'arts', target: 'literature', label: 'umfasst' },
{ source: 'arts', target: 'psychology', label: 'beeinflusst' },
// Psychologie-Verbindungen
{ source: 'psychology', target: 'cognitive', label: 'umfasst' },
{ source: 'psychology', target: 'behavioral', label: 'umfasst' },
{ source: 'psychology', target: 'ethics', label: 'beeinflusst' },
// Interdisziplinäre Verbindungen
{ source: 'cognitive', target: 'ai', label: 'inspiriert' },
{ source: 'physics', target: 'technology', label: 'ermöglicht' },
{ source: 'literature', target: 'philosophy', label: 'reflektiert' }
]
};
// Mindmap aktualisieren
function updateMindmap() {
if (!cy) return;
// Bestehende Elemente entfernen
cy.elements().remove();
// Neue Knoten hinzufügen
mindmapData.nodes.forEach(node => {
cy.add({
group: 'nodes',
data: {
id: node.id,
label: node.label,
category: node.category,
description: node.description
}
});
});
// Neue Kanten hinzufügen
mindmapData.edges.forEach(edge => {
cy.add({
group: 'edges',
data: {
source: edge.source,
target: edge.target,
label: edge.label
}
});
});
// Layout anwenden
cy.layout({
name: 'cose',
idealEdgeLength: 100,
nodeOverlap: 20,
refresh: 20,
fit: true,
padding: 30,
randomize: false,
componentSpacing: 100,
nodeRepulsion: 400000,
edgeElasticity: 100,
nestingFactor: 5,
gravity: 80,
numIter: 1000,
initialTemp: 200,
coolingFactor: 0.95,
minTemp: 1.0
}).run();
}
/**
* Erweitert die Mindmap mit den neu hinzugefügten wissenschaftlichen Knoten
* Erweitert die Mindmap mit dem neuronalen Netzwerk-Design
*/
function enhanceMindmap() {
// Auf die bestehende Cytoscape-Instanz zugreifen
@@ -33,25 +223,295 @@ function enhanceMindmap() {
return;
}
// Aktualisiere das Layout mit zusätzlichem Platz für die neuen Knoten
// Aktualisiere das Layout für eine bessere Verteilung
cy.layout({
name: 'cose',
animate: true,
animationDuration: 800,
animationDuration: 1800,
nodeDimensionsIncludeLabels: true,
padding: 100,
spacingFactor: 1.8,
randomize: false,
fit: true
fit: true,
componentSpacing: 100,
nodeRepulsion: 8000,
edgeElasticity: 100,
nestingFactor: 1.2,
gravity: 80
}).run();
console.log('Mindmap wurde erfolgreich aktualisiert!');
// Neuronen-Namen mit besserer Lesbarkeit umgestalten
cy.style()
.selector('node')
.style({
'text-background-color': 'rgba(10, 14, 25, 0.7)',
'text-background-opacity': 0.7,
'text-background-padding': '2px',
'text-border-opacity': 0.2,
'text-border-width': 1,
'text-border-color': '#8b5cf6'
})
.update();
// Wenn ein Wissen-Knoten existiert, sicherstellen, dass er im Zentrum ist
const rootNode = cy.getElementById('1');
if (rootNode.length > 0) {
cy.center(rootNode);
// Sicherstellen, dass alle Knoten Neuronen-Eigenschaften haben
cy.nodes().forEach(node => {
if (!node.data('neuronSize')) {
const neuronSize = Math.floor(Math.random() * 8) + 3;
node.data('neuronSize', neuronSize);
}
if (!node.data('neuronActivity')) {
const neuronActivity = Math.random() * 0.7 + 0.3;
node.data('neuronActivity', neuronActivity);
}
// Zusätzliche Neuronale Eigenschaften
node.data('pulseFrequency', Math.random() * 4 + 2); // Pulsfrequenz (2-6 Hz)
node.data('refractionPeriod', Math.random() * 300 + 700); // Refraktionszeit (700-1000ms)
node.data('threshold', Math.random() * 0.3 + 0.6); // Aktivierungsschwelle (0.6-0.9)
});
// Sicherstellen, dass alle Kanten Synapse-Eigenschaften haben
cy.edges().forEach(edge => {
if (!edge.data('strength')) {
const strength = Math.random() * 0.6 + 0.2;
edge.data('strength', strength);
}
// Zusätzliche synaptische Eigenschaften
edge.data('conductionVelocity', Math.random() * 0.5 + 0.3); // Leitungsgeschwindigkeit (0.3-0.8)
edge.data('latency', Math.random() * 100 + 50); // Signalverzögerung (50-150ms)
});
// Neuronales Netzwerk-Stil anwenden
applyNeuralNetworkStyle(cy);
console.log('Mindmap wurde erfolgreich im neuronalen Netzwerk-Stil aktualisiert');
// Spezielle Effekte für das neuronale Netzwerk hinzufügen
startNeuralActivitySimulation(cy);
}
/**
* Wendet detaillierte neuronale Netzwerkstile auf die Mindmap an
* @param {Object} cy - Cytoscape-Instanz
*/
function applyNeuralNetworkStyle(cy) {
// Wende erweiterte Stile für Neuronen und Synapsen an
cy.style()
.selector('node')
.style({
'label': 'data(name)',
'text-valign': 'bottom',
'text-halign': 'center',
'color': '#ffffff',
'text-outline-width': 1.5,
'text-outline-color': '#0a0e19',
'text-outline-opacity': 0.9,
'font-size': 10,
'text-margin-y': 7,
'width': 'mapData(neuronSize, 3, 10, 15, 40)',
'height': 'mapData(neuronSize, 3, 10, 15, 40)',
'background-color': 'data(color)',
'background-opacity': 0.85,
'border-width': 0,
'shape': 'ellipse',
'shadow-blur': 'mapData(neuronActivity, 0.3, 1, 5, 15)',
'shadow-color': 'data(color)',
'shadow-opacity': 0.6,
'shadow-offset-x': 0,
'shadow-offset-y': 0
})
.selector('edge')
.style({
'width': 'mapData(strength, 0.2, 0.8, 0.7, 2)',
'curve-style': 'bezier',
'line-color': '#8a8aaa',
'line-opacity': 'mapData(strength, 0.2, 0.8, 0.4, 0.7)',
'line-style': function(ele) {
const strength = ele.data('strength');
if (strength <= 0.4) return 'dotted';
if (strength <= 0.6) return 'dashed';
return 'solid';
},
'target-arrow-shape': 'none',
'source-endpoint': '0% 50%',
'target-endpoint': '100% 50%'
})
.selector('node[isRoot]')
.style({
'font-size': 12,
'font-weight': 'bold',
'width': 50,
'height': 50,
'background-color': '#6366f1',
'shadow-blur': 20,
'shadow-color': '#6366f1',
'shadow-opacity': 0.8,
'text-margin-y': 8
})
.update();
}
/**
* Simuliert neuronale Aktivität in der Mindmap
* @param {Object} cy - Cytoscape-Instanz
*/
function startNeuralActivitySimulation(cy) {
// Neuronen-Zustand für die Simulation
const neuronStates = new Map();
// Initialisieren aller Neuronen-Zustände
cy.nodes().forEach(node => {
neuronStates.set(node.id(), {
potential: Math.random() * 0.3, // Startpotential
lastFired: 0, // Zeitpunkt der letzten Aktivierung
isRefractory: false, // Refraktärphase
refractoryUntil: 0 // Ende der Refraktärphase
});
});
// Neuronale Aktivität simulieren
function simulateNeuralActivity() {
const currentTime = Date.now();
const nodes = cy.nodes().toArray();
// Zufällige Stimulation eines Neurons
if (Math.random() > 0.7) {
const randomNodeIndex = Math.floor(Math.random() * nodes.length);
const randomNode = nodes[randomNodeIndex];
const state = neuronStates.get(randomNode.id());
if (state && !state.isRefractory) {
state.potential += 0.5; // Erhöhe das Potential durch externe Stimulation
}
}
// Neuronen aktualisieren
nodes.forEach(node => {
const nodeId = node.id();
const state = neuronStates.get(nodeId);
const threshold = node.data('threshold') || 0.7;
const refractoryPeriod = node.data('refractionPeriod') || 1000;
// Überprüfen, ob die Refraktärphase beendet ist
if (state.isRefractory && currentTime >= state.refractoryUntil) {
state.isRefractory = false;
state.potential = 0.1; // Ruhepotential nach Refraktärphase
}
// Wenn nicht in Refraktärphase und Potential über Schwelle
if (!state.isRefractory && state.potential >= threshold) {
// Neuron feuert
fireNeuron(node, state, currentTime);
} else if (!state.isRefractory) {
// Potential langsam verlieren, wenn nicht gefeuert wird
state.potential *= 0.95;
}
});
// Simulation fortsetzen
requestAnimationFrame(simulateNeuralActivity);
}
// Neuron "feuern" lassen
function fireNeuron(node, state, currentTime) {
// Neuron aktivieren
node.animate({
style: {
'background-opacity': 1,
'shadow-opacity': 1,
'shadow-blur': 25
},
duration: 300,
easing: 'ease-in-cubic',
complete: function() {
// Zurück zum normalen Zustand
node.animate({
style: {
'background-opacity': 0.85,
'shadow-opacity': 0.6,
'shadow-blur': 'mapData(neuronActivity, 0.3, 1, 5, 15)'
},
duration: 600,
easing: 'ease-out-cubic'
});
}
});
// Refraktärphase setzen
state.isRefractory = true;
state.lastFired = currentTime;
state.refractoryPeriod = node.data('refractionPeriod') || 1000;
state.refractoryUntil = currentTime + state.refractoryPeriod;
state.potential = 0; // Potential zurücksetzen
// Signal über verbundene Synapsen weiterleiten
propagateSignal(node, currentTime);
}
// Signal über Synapsen propagieren
function propagateSignal(sourceNode, currentTime) {
// Verbundene Kanten auswählen
const edges = sourceNode.connectedEdges().filter(edge =>
edge.source().id() === sourceNode.id() // Nur ausgehende Kanten
);
// Durch alle Kanten iterieren
edges.forEach(edge => {
// Signalverzögerung basierend auf synaptischen Eigenschaften
const latency = edge.data('latency') || 100;
const strength = edge.data('strength') || 0.5;
// Signal entlang der Kante senden
setTimeout(() => {
edge.animate({
style: {
'line-color': '#a78bfa',
'line-opacity': 0.9,
'width': 2.5
},
duration: 200,
easing: 'ease-in',
complete: function() {
// Kante zurücksetzen
edge.animate({
style: {
'line-color': '#8a8aaa',
'line-opacity': 'mapData(strength, 0.2, 0.8, 0.4, 0.7)',
'width': 'mapData(strength, 0.2, 0.8, 0.7, 2)'
},
duration: 400,
easing: 'ease-out'
});
// Zielknoten potenzial erhöhen
const targetNode = edge.target();
const targetState = neuronStates.get(targetNode.id());
if (targetState && !targetState.isRefractory) {
// Potentialzunahme basierend auf synaptischer Stärke
targetState.potential += strength * 0.4;
// Subtile Anzeige der Potenzialänderung
targetNode.animate({
style: {
'background-opacity': Math.min(1, 0.85 + (strength * 0.2)),
'shadow-opacity': Math.min(1, 0.6 + (strength * 0.3)),
'shadow-blur': Math.min(25, 10 + (strength * 15))
},
duration: 300,
easing: 'ease-in-out'
});
}
}
});
}, latency);
});
}
// Starte die Simulation
simulateNeuralActivity();
}
// Hilfe-Funktion zum Hinzufügen eines Flash-Hinweises

View File

@@ -1,402 +1,228 @@
{% extends "base.html" %}
{% block title %}Mindmap{% endblock %}
{% block title %}Interaktive Mindmap{% endblock %}
{% block extra_css %}
<style>
/* Spezifische Stile für die Mindmap-Seite */
/* Grundlegendes Layout */
.mindmap-container {
position: relative;
width: 100%;
height: calc(100vh - 64px);
background: linear-gradient(135deg, #1a1f2e 0%, #0f172a 100%);
overflow: hidden;
}
/* Hauptcontainer für die Mindmap */
#cy {
width: 100%;
height: 750px;
background-color: var(--bg-secondary);
transition: background-color 0.3s ease;
border-radius: 10px;
overflow: hidden;
position: relative;
height: 100%;
background: transparent;
}
/* Hintergrundraster für wissenschaftliches Aussehen */
#cy::before {
content: '';
/* Header-Bereich */
.mindmap-header {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
background-size: 20px 20px;
pointer-events: none;
z-index: 1;
}
.dark #cy::before {
background-image:
linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
}
/* Verbesserte Mindmap-Container-Stile */
.mindmap-container {
position: relative;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
background-color: var(--bg-secondary);
}
.dark .mindmap-container {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
background-color: var(--bg-secondary);
}
/* Flüssigere Übergänge für Mindmap-Elemente */
.mindmap-svg {
transition: background-color 0.5s ease;
}
.node {
cursor: pointer;
transition: opacity 0.3s ease, transform 0.3s ease;
}
.node:hover {
transform: scale(1.05);
}
.node circle {
transition: r 0.3s ease, fill 0.3s ease, stroke 0.3s ease, stroke-width 0.3s ease, filter 0.3s ease;
}
.node text {
transition: font-size 0.3s ease, fill 0.3s ease;
user-select: none;
}
.link {
transition: stroke 0.3s ease, stroke-width 0.3s ease, opacity 0.3s ease;
pointer-events: none;
}
/* Panel-Übergänge für Seitenleiste */
[data-sidebar] {
transition: opacity 0.3s ease, transform 0.3s ease, display 0s linear 0.3s;
}
[data-sidebar].active {
transition: opacity 0.3s ease, transform 0.3s ease, display 0s linear;
}
/* Mindmap-Toolbar mit verbessertem Erscheinungsbild */
.mindmap-toolbar {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
padding: 0.75rem;
background-color: var(--bg-secondary);
padding: 1.5rem;
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
transition: background-color 0.3s ease;
position: relative;
z-index: 10;
}
body:not(.dark) .mindmap-toolbar {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.mindmap-title {
font-size: 2rem;
font-weight: 700;
color: #fff;
margin: 0;
background: linear-gradient(90deg, #60a5fa, #8b5cf6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Verbesserte Button-Stile für Mindmap-Toolbar */
.mindmap-action-btn {
/* Kontrollpanel */
.control-panel {
position: absolute;
right: 2rem;
top: 50%;
transform: translateY(-50%);
background: rgba(15, 23, 42, 0.9);
border-radius: 1rem;
padding: 1.5rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
z-index: 10;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.control-button {
display: flex;
align-items: center;
gap: 0.35rem;
padding: 0.35rem 0.7rem;
font-size: 0.8rem;
border-radius: 0.25rem;
background-color: rgba(79, 70, 229, 0.1);
color: #4f46e5;
border: 1px solid rgba(79, 70, 229, 0.2);
padding: 0.75rem 1rem;
margin: 0.5rem 0;
background: rgba(255, 255, 255, 0.1);
border: none;
border-radius: 0.5rem;
color: #fff;
cursor: pointer;
transition: all 0.2s ease;
}
.dark .mindmap-action-btn {
background-color: rgba(79, 70, 229, 0.15);
border-color: rgba(79, 70, 229, 0.3);
}
.mindmap-action-btn:hover {
background-color: rgba(79, 70, 229, 0.2);
transform: translateY(-1px);
}
.mindmap-action-btn:active {
transform: translateY(0);
}
/* Verbesserte Seitenleisten-Panels mit Animation */
.sidebar-panel {
transition: all 0.3s ease-in-out;
}
.sidebar-panel.hidden {
opacity: 0;
transform: translateY(10px);
}
.sidebar-panel.visible {
opacity: 1;
transform: translateY(0);
}
/* Info-Panel anpassungen */
.mindmap-info-panel {
position: absolute;
right: 1rem;
top: 5rem;
width: 280px;
background-color: rgba(15, 23, 42, 0.85);
border-radius: 8px;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
padding: 1rem;
color: #f1f5f9;
opacity: 0;
transform: translateX(20px);
transition: all 0.3s ease;
pointer-events: none;
}
.control-button:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateX(-5px);
}
.control-button i {
margin-right: 0.75rem;
}
/* Info-Panel */
.info-panel {
position: absolute;
left: 2rem;
top: 50%;
transform: translateY(-50%);
background: rgba(15, 23, 42, 0.9);
border-radius: 1rem;
padding: 1.5rem;
width: 300px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
z-index: 10;
backdrop-filter: blur(4px);
border: 1px solid rgba(255, 255, 255, 0.1);
opacity: 0;
transform: translateX(-20px);
transition: all 0.3s ease;
}
.mindmap-info-panel.visible {
.info-panel.visible {
opacity: 1;
transform: translateX(0);
pointer-events: auto;
transform: translateY(-50%) translateX(0);
}
.info-panel-title {
font-size: 1.1rem;
.info-title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: #fff;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.info-panel-description {
font-size: 0.875rem;
margin-bottom: 1rem;
line-height: 1.5;
.info-content {
color: rgba(255, 255, 255, 0.8);
font-size: 0.95rem;
line-height: 1.6;
}
.node-navigation-title {
font-size: 0.9rem;
font-weight: 500;
margin-bottom: 0.5rem;
}
.node-links {
/* Kategorie-Legende */
.category-legend {
position: absolute;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
background: rgba(15, 23, 42, 0.9);
border-radius: 1rem;
padding: 1rem 2rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.node-link {
display: inline-block;
padding: 0.25rem 0.5rem;
font-size: 0.75rem;
border-radius: 4px;
cursor: pointer;
transition: transform 0.2s ease;
color: white;
}
.node-link:hover {
transform: translateY(-2px);
}
/* Zusätzliches Layout */
.mindmap-section {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
z-index: 10;
border: 1px solid rgba(255, 255, 255, 0.1);
}
@media (min-width: 1024px) {
.mindmap-section {
grid-template-columns: 2fr 1fr;
}
.category-item {
display: flex;
align-items: center;
color: rgba(255, 255, 255, 0.8);
font-size: 0.9rem;
}
.category-color {
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 0.5rem;
}
/* Animationen */
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s infinite;
}
</style>
{% endblock %}
{% block content %}
<div class="container mx-auto px-4 py-8">
<div class="flex flex-col lg:flex-row gap-8">
<!-- Hauptinhalt -->
<div class="w-full lg:w-3/4">
<!-- Mindmap-Titelbereich -->
<div class="mb-6">
<h1 class="text-3xl font-bold mb-2 mystical-glow"
x-bind:class="darkMode ? 'text-white' : 'text-gray-800'">
Wissenslandkarte
</h1>
<p class="opacity-80 text-lg"
x-bind:class="darkMode ? 'text-gray-300' : 'text-gray-600'">
Visualisiere die Verbindungen zwischen Gedanken und Konzepten
</p>
</div>
<div class="mindmap-container">
<!-- Header -->
<div class="mindmap-header">
<h1 class="mindmap-title">Interaktive Wissenslandkarte</h1>
</div>
<!-- Mindmap-Container -->
<div class="mindmap-container">
<!-- Toolbar -->
<div class="mindmap-toolbar">
<button id="fit-btn" class="mindmap-action-btn" title="An Fenstergröße anpassen">
<i class="fa-solid fa-expand"></i>
<span>Anpassen</span>
</button>
<button id="reset-btn" class="mindmap-action-btn" title="Ansicht zurücksetzen">
<i class="fa-solid fa-undo"></i>
<span>Zurücksetzen</span>
</button>
<button id="zoom-in-btn" class="mindmap-action-btn" title="Einzoomen">
<i class="fa-solid fa-magnifying-glass-plus"></i>
<span>Zoom+</span>
</button>
<button id="zoom-out-btn" class="mindmap-action-btn" title="Auszoomen">
<i class="fa-solid fa-magnifying-glass-minus"></i>
<span>Zoom-</span>
</button>
<button id="toggle-labels-btn" class="mindmap-action-btn" title="Labels ein/ausblenden">
<i class="fa-solid fa-tags"></i>
<span>Labels</span>
</button>
<button id="fullscreen-btn" class="mindmap-action-btn" title="Vollbildmodus">
<i class="fa-solid fa-expand"></i>
<span>Vollbild</span>
</button>
</div>
<!-- Hauptvisualisierung -->
<div id="cy"></div>
<!-- Hauptvisualisierung -->
<div id="cy"></div>
<!-- Kontrollpanel -->
<div class="control-panel">
<button class="control-button" id="zoom-in">
<i class="fas fa-search-plus"></i> Einzoomen
</button>
<button class="control-button" id="zoom-out">
<i class="fas fa-search-minus"></i> Auszoomen
</button>
<button class="control-button" id="reset-view">
<i class="fas fa-compress-arrows-alt"></i> Ansicht zurücksetzen
</button>
<button class="control-button" id="toggle-legend">
<i class="fas fa-layer-group"></i> Legende ein/aus
</button>
</div>
<!-- Info-Panel -->
<div id="node-info-panel" class="mindmap-info-panel">
<h4 class="info-panel-title">Knoteninfo</h4>
<p id="node-description" class="info-panel-description">Wählen Sie einen Knoten aus...</p>
<div class="node-navigation">
<h5 class="node-navigation-title">Verknüpfte Knoten</h5>
<div id="connected-nodes" class="node-links">
<!-- Wird dynamisch befüllt -->
</div>
</div>
</div>
</div>
<!-- Info-Panel -->
<div class="info-panel" id="node-info">
<h3 class="info-title">Knoteninformationen</h3>
<div class="info-content">
<p>Wählen Sie einen Knoten aus, um Details anzuzeigen.</p>
</div>
</div>
<!-- Seitenleiste -->
<div class="w-full lg:w-1/4 space-y-6">
<!-- Nutzlänge -->
<div class="p-5 rounded-lg overflow-hidden border transition-colors duration-300"
x-bind:class="darkMode ? 'bg-slate-800/40 border-slate-700/50' : 'bg-white border-slate-200'"
data-sidebar="about-mindmap">
<h3 class="text-xl font-semibold mb-3"
x-bind:class="darkMode ? 'text-white' : 'text-gray-800'">
<i class="fa-solid fa-circle-info text-purple-400 mr-2"></i>Über die Mindmap
</h3>
<div x-bind:class="darkMode ? 'text-gray-300' : 'text-gray-600'">
<p class="mb-2">Die interaktive Wissenslandkarte zeigt Verbindungen zwischen verschiedenen Gedanken und Konzepten.</p>
<p class="mb-2">Sie können:</p>
<ul class="list-disc pl-5 space-y-1 text-sm">
<li>Knoten auswählen, um Details zu sehen</li>
<li>Zoomen (Mausrad oder Pinch-Geste)</li>
<li>Die Karte verschieben (Drag & Drop)</li>
<li>Die Toolbar nutzen für weitere Aktionen</li>
</ul>
</div>
</div>
<!-- Kategorienlegende -->
<div class="p-5 rounded-lg overflow-hidden border transition-colors duration-300"
x-bind:class="darkMode ? 'bg-slate-800/40 border-slate-700/50' : 'bg-white border-slate-200'"
data-sidebar="categories">
<h3 class="text-xl font-semibold mb-3"
x-bind:class="darkMode ? 'text-white' : 'text-gray-800'">
<i class="fa-solid fa-palette text-purple-400 mr-2"></i>Kategorien
</h3>
<div id="category-legend" class="space-y-2 text-sm"
x-bind:class="darkMode ? 'text-gray-300' : 'text-gray-600'">
<!-- Wird dynamisch befüllt -->
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-indigo-600 mr-2"></span> Philosophie</div>
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-emerald-600 mr-2"></span> Wissenschaft</div>
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-indigo-500 mr-2"></span> Technologie</div>
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-violet-500 mr-2"></span> Künste</div>
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-cyan-700 mr-2"></span> Psychologie</div>
</div>
</div>
<!-- Knotenbeschreibung (anfangs ausgeblendet) -->
<div class="p-5 rounded-lg overflow-hidden border transition-colors duration-300 hidden"
x-bind:class="darkMode ? 'bg-slate-800/40 border-slate-700/50' : 'bg-white border-slate-200'"
data-sidebar="node-description">
<h3 class="text-xl font-semibold mb-3"
x-bind:class="darkMode ? 'text-white' : 'text-gray-800'"
data-node-title>Knotenbeschreibung</h3>
<div class="space-y-3" x-bind:class="darkMode ? 'text-gray-300' : 'text-gray-600'">
<p class="text-sm leading-relaxed" data-node-description>
Wählen Sie einen Knoten in der Mindmap aus, um dessen Beschreibung hier anzuzeigen.
</p>
<div class="pt-2 mt-2 border-t" x-bind:class="darkMode ? 'border-slate-700/50' : 'border-slate-200'">
<button class="text-xs px-3 py-1.5 rounded bg-indigo-100 text-indigo-700 hover:bg-indigo-200 transition-colors dark:bg-indigo-900/30 dark:text-indigo-300 dark:hover:bg-indigo-800/40"
onclick="window.mindmapInstance && window.mindmapInstance.selectedNode && window.mindmapInstance.centerNodeInView(window.mindmapInstance.selectedNode)">
<i class="fa-solid fa-crosshairs mr-1"></i> Knoten zentrieren
</button>
</div>
</div>
</div>
<!-- Meine Mindmaps -->
{% if current_user.is_authenticated %}
<div class="p-5 rounded-lg overflow-hidden border transition-colors duration-300"
x-bind:class="darkMode ? 'bg-slate-800/40 border-slate-700/50' : 'bg-white border-slate-200'">
<h3 class="text-xl font-semibold mb-3"
x-bind:class="darkMode ? 'text-white' : 'text-gray-800'">
<i class="fa-solid fa-map text-purple-400 mr-2"></i>Meine Mindmaps
</h3>
<div class="mb-3">
<a href="{{ url_for('create_mindmap') }}" class="w-full inline-block py-2 px-4 bg-purple-600 hover:bg-purple-700 text-white rounded-lg text-center text-sm font-medium transition-colors">
<i class="fa-solid fa-plus mr-1"></i> Neue Mindmap erstellen
</a>
</div>
<div class="space-y-2 max-h-60 overflow-y-auto"
x-bind:class="darkMode ? 'text-gray-300' : 'text-gray-600'">
{% if user_mindmaps %}
{% for mindmap in user_mindmaps %}
<a href="{{ url_for('user_mindmap', mindmap_id=mindmap.id) }}" class="block p-2 hover:bg-purple-500/20 rounded-lg transition-colors">
<div class="text-sm font-medium">{{ mindmap.name }}</div>
<div class="text-xs opacity-70">{{ mindmap.nodes|length }} Knoten</div>
</a>
{% endfor %}
{% else %}
<p class="text-sm italic">Sie haben noch keine eigenen Mindmaps erstellt.</p>
{% endif %}
</div>
</div>
{% endif %}
<!-- Kategorie-Legende -->
<div class="category-legend">
<div class="category-item">
<span class="category-color" style="background: #60a5fa;"></span>
Philosophie
</div>
<div class="category-item">
<span class="category-color" style="background: #8b5cf6;"></span>
Wissenschaft
</div>
<div class="category-item">
<span class="category-color" style="background: #10b981;"></span>
Technologie
</div>
<div class="category-item">
<span class="category-color" style="background: #f59e0b;"></span>
Künste
</div>
<div class="category-item">
<span class="category-color" style="background: #ef4444;"></span>
Psychologie
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<!-- Cytoscape -->
<script src="{{ url_for('static', filename='js/cytoscape.min.js') }}"></script>
<!-- Mindmap initialisierung -->
<script src="{{ url_for('static', filename='js/mindmap-init.js') }}"></script>
<!-- Update Mindmap mit wissenschaftlichen Knoten -->
<script src="{{ url_for('static', filename='js/update_mindmap.js') }}"></script>
<!-- Verbesserte Interaktion -->
<script src="{{ url_for('static', filename='js/mindmap-interaction.js') }}"></script>
{% endblock %}