Files
website/static/js/mindmap-interaction.js

241 lines
6.5 KiB
JavaScript

/**
* Mindmap Interaction Enhancement
* Verbessert die Interaktion mit der Mindmap und steuert die Seitenleisten-Anzeige
*/
// Globale Variablen
let cy;
let selectedNode = null;
let isLegendVisible = true;
// 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;
}
});
});
// 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>';
}
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('');
}
// Farbe basierend auf Kategorie
function getNodeColor(category) {
const colors = {
'Philosophie': '#60a5fa',
'Wissenschaft': '#8b5cf6',
'Technologie': '#10b981',
'Künste': '#f59e0b',
'Psychologie': '#ef4444'
};
return colors[category] || '#60a5fa';
}