✨ feat(mindmap): verbessere die Benutzerinteraktion und das visuelle Design der Mindmap. Füge dynamische Knotenbeschreibungen hinzu, aktualisiere die Farbpalette und optimiere die Zoom- und Knoteninteraktionen. Erweitere die Seitenleisten mit neuen Panels und verbessere die Animationen für ein ansprechenderes Nutzererlebnis.
This commit is contained in:
260
static/js/mindmap-interaction.js
Normal file
260
static/js/mindmap-interaction.js
Normal file
@@ -0,0 +1,260 @@
|
||||
/**
|
||||
* Mindmap Interaction Enhancement
|
||||
* 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();
|
||||
});
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Initialisiert die Hover-Effekte für die Seitenleisten-Panels
|
||||
initializePanelEffects();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -56,25 +56,6 @@ class MindMapVisualization {
|
||||
'languages': '#2563eb' // Blau
|
||||
};
|
||||
|
||||
'default': '#b38fff',
|
||||
'root': '#7e3ff2',
|
||||
'philosophy': '#58a9ff',
|
||||
'science': '#38b2ac',
|
||||
'technology': '#6366f1',
|
||||
'arts': '#ec4899',
|
||||
'ai': '#8b5cf6',
|
||||
'ethics': '#f59e0b',
|
||||
'math': '#06b6d4',
|
||||
'psychology': '#10b981',
|
||||
'biology': '#84cc16',
|
||||
'literature': '#f43f5e',
|
||||
'history': '#fb7185',
|
||||
'economics': '#fbbf24',
|
||||
'sociology': '#a78bfa',
|
||||
'design': '#f472b6',
|
||||
'languages': '#4ade80'
|
||||
};
|
||||
|
||||
// Sicherstellen, dass der Container bereit ist
|
||||
if (this.container.node()) {
|
||||
this.init();
|
||||
@@ -457,22 +438,38 @@ class MindMapVisualization {
|
||||
.attr('slope', '1.5');
|
||||
}
|
||||
|
||||
// Behandelt die Zoom-Transformation für die SVG
|
||||
// Behandelt die Zoom-Transformation für die SVG mit verbesserter Anpassung
|
||||
handleZoom(transform) {
|
||||
this.g.attr('transform', transform);
|
||||
this.zoomFactor = transform.k;
|
||||
|
||||
// Knotengröße an Zoom anpassen
|
||||
// Knotengröße dynamisch an Zoom anpassen für bessere Lesbarkeit
|
||||
if (this.nodeElements) {
|
||||
// Berechne relativen Radius basierend auf Zoom
|
||||
const nodeScaleFactor = 1 / Math.sqrt(transform.k);
|
||||
const minRadiusFactor = 0.6; // Minimale Größe beim Herauszoomen
|
||||
const maxRadiusFactor = 1.2; // Maximale Größe beim Hineinzoomen
|
||||
|
||||
// Beschränke den Skalierungsfaktor in sinnvollen Grenzen
|
||||
const cappedScaleFactor = Math.max(minRadiusFactor, Math.min(nodeScaleFactor, maxRadiusFactor));
|
||||
|
||||
this.nodeElements.selectAll('circle')
|
||||
.attr('r', d => {
|
||||
return d === this.selectedNode
|
||||
? this.selectedNodeRadius / Math.sqrt(transform.k)
|
||||
: this.nodeRadius / Math.sqrt(transform.k);
|
||||
});
|
||||
? this.selectedNodeRadius * cappedScaleFactor
|
||||
: this.nodeRadius * cappedScaleFactor;
|
||||
})
|
||||
.attr('stroke-width', 2 * cappedScaleFactor); // Strichstärke anpassen
|
||||
|
||||
this.textElements
|
||||
.style('font-size', `${16 / Math.sqrt(transform.k)}px`);
|
||||
// Schriftgröße dynamisch anpassen
|
||||
this.nodeElements.selectAll('text')
|
||||
.style('font-size', `${14 * cappedScaleFactor}px`)
|
||||
.attr('dy', 4 * cappedScaleFactor);
|
||||
|
||||
// Verbindungslinien anpassen
|
||||
this.linkElements
|
||||
.attr('stroke-width', 1.5 * cappedScaleFactor)
|
||||
.attr('marker-end', transform.k < 0.6 ? 'none' : 'url(#arrowhead)'); // Pfeile bei starkem Zoom ausblenden
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,9 +737,10 @@ class MindMapVisualization {
|
||||
|
||||
// Generiert eine konsistente Farbe basierend auf dem Knotennamen
|
||||
generateColorFromString(str) {
|
||||
// Authentischere, dezente Farben für wissenschaftliche Darstellung
|
||||
const colors = [
|
||||
'#b38fff', '#58a9ff', '#14b8a6', '#f472b6', '#84cc16',
|
||||
'#f97316', '#4c1d95', '#2dd4bf', '#ec4899', '#eab308'
|
||||
'#4f46e5', '#0369a1', '#0f766e', '#374151', '#4338ca',
|
||||
'#0284c7', '#059669', '#475569', '#6366f1', '#0891b2'
|
||||
];
|
||||
|
||||
let hash = 0;
|
||||
@@ -883,9 +881,11 @@ class MindMapVisualization {
|
||||
return node.color_code;
|
||||
}
|
||||
|
||||
// Kategorietyp-basierte Färbung
|
||||
if (node.type === 'category' || node.type === 'subcategory') {
|
||||
// Kategorietyp-basierte Färbung mit dezenten, wissenschaftlichen Farben
|
||||
if (node.type === 'category') {
|
||||
return this.colorPalette.root;
|
||||
} else if (node.type === 'subcategory') {
|
||||
return this.colorPalette.science;
|
||||
}
|
||||
|
||||
// Fallback für verschiedene Knotentypen
|
||||
@@ -1208,7 +1208,7 @@ class MindMapVisualization {
|
||||
});
|
||||
}
|
||||
|
||||
// Klick-Handler für Knoten
|
||||
// Klick-Handler für Knoten mit verbesserter Seitenleisten-Interaktion
|
||||
nodeClicked(event, d) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -1227,6 +1227,9 @@ class MindMapVisualization {
|
||||
.style('filter', 'url(#glass-with-reflection)')
|
||||
.attr('stroke-width', 2);
|
||||
|
||||
// Standardinformationspanels wieder anzeigen
|
||||
this.showDefaultSidebar();
|
||||
|
||||
// Gedankenbereich ausblenden, wenn vorhanden
|
||||
const thoughtContainer = document.getElementById('thought-container');
|
||||
if (thoughtContainer) {
|
||||
@@ -1257,7 +1260,7 @@ class MindMapVisualization {
|
||||
.classed('highlighted', false)
|
||||
.transition()
|
||||
.duration(300)
|
||||
.style('stroke', 'rgba(255, 255, 255, 0.3)')
|
||||
.style('stroke', 'rgba(75, 85, 99, 0.4)')
|
||||
.style('stroke-width', 2)
|
||||
.style('opacity', 0.7);
|
||||
|
||||
@@ -1301,7 +1304,7 @@ class MindMapVisualization {
|
||||
.attr('r', this.selectedNodeRadius)
|
||||
.style('filter', 'url(#selected-glow)')
|
||||
.attr('stroke-width', 3)
|
||||
.attr('stroke', 'rgba(179, 143, 255, 0.6)');
|
||||
.attr('stroke', 'rgba(79, 70, 229, 0.6)');
|
||||
|
||||
// Verbundene Kanten hervorheben
|
||||
const connectedLinks = this.links.filter(link =>
|
||||
@@ -1314,7 +1317,7 @@ class MindMapVisualization {
|
||||
.classed('highlighted', false)
|
||||
.transition()
|
||||
.duration(300)
|
||||
.style('stroke', 'rgba(255, 255, 255, 0.3)')
|
||||
.style('stroke', 'rgba(75, 85, 99, 0.4)')
|
||||
.style('stroke-width', 2)
|
||||
.style('opacity', 0.7);
|
||||
|
||||
@@ -1328,13 +1331,16 @@ class MindMapVisualization {
|
||||
.classed('highlighted', true)
|
||||
.transition()
|
||||
.duration(300)
|
||||
.style('stroke', 'rgba(179, 143, 255, 0.7)')
|
||||
.style('stroke', 'rgba(79, 70, 229, 0.7)')
|
||||
.style('stroke-width', 3)
|
||||
.style('opacity', 0.9);
|
||||
|
||||
// Knoten zentrieren
|
||||
this.centerNodeInView(d);
|
||||
|
||||
// Knotenbeschreibung in der Seitenleiste anzeigen
|
||||
this.showNodeDescriptionSidebar(d);
|
||||
|
||||
// Gedanken laden
|
||||
this.loadThoughtsForNode(d);
|
||||
|
||||
@@ -1349,6 +1355,133 @@ class MindMapVisualization {
|
||||
}
|
||||
}
|
||||
|
||||
// Neue Methode: Zeigt die Standardseitenleiste an (Über die Mindmap und Kategorien)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Neue Methode: Zeigt die Knotenbeschreibung in der Seitenleiste an
|
||||
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 = this.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);
|
||||
}
|
||||
}
|
||||
|
||||
// Neue Methode: Generiert automatisch eine Beschreibung für einen Knoten ohne Beschreibung
|
||||
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."
|
||||
};
|
||||
|
||||
// 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.`;
|
||||
}
|
||||
}
|
||||
|
||||
// Lädt die Gedanken für einen Knoten und zeigt sie an
|
||||
loadThoughtsForNode(node) {
|
||||
// UI-Element für Gedanken finden
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
/* Spezifische Stile für die Mindmap-Seite */
|
||||
#cy {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
height: 750px;
|
||||
background-color: var(--bg-secondary);
|
||||
transition: background-color 0.3s ease;
|
||||
border-radius: 10px;
|
||||
@@ -15,18 +15,81 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Hintergrundraster für wissenschaftliches Aussehen */
|
||||
#cy::before {
|
||||
content: '';
|
||||
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;
|
||||
@@ -35,82 +98,59 @@
|
||||
background-color: var(--bg-secondary);
|
||||
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);
|
||||
}
|
||||
|
||||
.btn {
|
||||
/* Verbesserte Button-Stile für Mindmap-Toolbar */
|
||||
.mindmap-action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.375rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.category-filters {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
flex-wrap: wrap;
|
||||
padding: 0.75rem;
|
||||
background-color: var(--bg-secondary);
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.category-filter {
|
||||
border: none;
|
||||
gap: 0.35rem;
|
||||
padding: 0.35rem 0.7rem;
|
||||
font-size: 0.8rem;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 0.75rem;
|
||||
background-color: rgba(79, 70, 229, 0.1);
|
||||
color: #4f46e5;
|
||||
border: 1px solid rgba(79, 70, 229, 0.2);
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s;
|
||||
color: white;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.category-filter:not(.active) {
|
||||
opacity: 0.6;
|
||||
.dark .mindmap-action-btn {
|
||||
background-color: rgba(79, 70, 229, 0.15);
|
||||
border-color: rgba(79, 70, 229, 0.3);
|
||||
}
|
||||
|
||||
.category-filter:hover:not(.active) {
|
||||
opacity: 0.8;
|
||||
.mindmap-action-btn:hover {
|
||||
background-color: rgba(79, 70, 229, 0.2);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Kontextmenü */
|
||||
#context-menu {
|
||||
position: absolute;
|
||||
border-radius: 0.375rem;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
.mindmap-action-btn:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.dark #context-menu {
|
||||
background-color: #232837;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
/* Verbesserte Seitenleisten-Panels mit Animation */
|
||||
.sidebar-panel {
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
body:not(.dark) #context-menu {
|
||||
background-color: white;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
.sidebar-panel.hidden {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
#context-menu .menu-item {
|
||||
padding: 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease;
|
||||
.sidebar-panel.visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.dark #context-menu .menu-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
body:not(.dark) #context-menu .menu-item:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* Info-Panel */
|
||||
/* Info-Panel anpassungen */
|
||||
.mindmap-info-panel {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
@@ -175,30 +215,6 @@
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Mindmap-Toolbar-Buttons */
|
||||
.mindmap-action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
padding: 0.35rem 0.7rem;
|
||||
font-size: 0.8rem;
|
||||
border-radius: 0.25rem;
|
||||
background-color: rgba(124, 58, 237, 0.1);
|
||||
color: #8b5cf6;
|
||||
border: 1px solid rgba(124, 58, 237, 0.2);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.dark .mindmap-action-btn {
|
||||
background-color: rgba(124, 58, 237, 0.15);
|
||||
border-color: rgba(124, 58, 237, 0.3);
|
||||
}
|
||||
|
||||
.mindmap-action-btn:hover {
|
||||
background-color: rgba(124, 58, 237, 0.2);
|
||||
}
|
||||
|
||||
/* Zusätzliches Layout */
|
||||
.mindmap-section {
|
||||
display: grid;
|
||||
@@ -235,17 +251,29 @@
|
||||
<div class="mindmap-container">
|
||||
<!-- Toolbar -->
|
||||
<div class="mindmap-toolbar">
|
||||
<button id="fit-btn" class="mindmap-action-btn">
|
||||
<button id="fit-btn" class="mindmap-action-btn" title="An Fenstergröße anpassen">
|
||||
<i class="fa-solid fa-expand"></i>
|
||||
<span>Ansicht anpassen</span>
|
||||
<span>Anpassen</span>
|
||||
</button>
|
||||
<button id="reset-btn" class="mindmap-action-btn">
|
||||
<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="toggle-labels-btn" class="mindmap-action-btn">
|
||||
<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 ein/aus</span>
|
||||
<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>
|
||||
|
||||
@@ -271,7 +299,8 @@
|
||||
<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'">
|
||||
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
|
||||
@@ -290,7 +319,8 @@
|
||||
|
||||
<!-- 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'">
|
||||
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
|
||||
@@ -298,11 +328,31 @@
|
||||
<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-purple-500 mr-2"></span> Philosophie</div>
|
||||
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-green-500 mr-2"></span> Wissenschaft</div>
|
||||
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-orange-500 mr-2"></span> Technologie</div>
|
||||
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-pink-500 mr-2"></span> Künste</div>
|
||||
<div class="flex items-center"><span class="w-3 h-3 rounded-full bg-blue-500 mr-2"></span> Psychologie</div>
|
||||
<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>
|
||||
|
||||
@@ -347,4 +397,6 @@
|
||||
<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 %}
|
||||
Reference in New Issue
Block a user