From 7cb2bf1ed0a6d1f3fdf4af9802e7be457af1bf99 Mon Sep 17 00:00:00 2001 From: marwin Date: Sat, 10 May 2025 20:40:13 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20enhance=20mindmap=20and=20n?= =?UTF-8?q?eural=20network=20background=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/update_mindmap.js | 261 +++++++++++++---------- static/neural-network-background-full.js | 62 +++++- 2 files changed, 210 insertions(+), 113 deletions(-) diff --git a/static/js/update_mindmap.js b/static/js/update_mindmap.js index 08e6063..b589e45 100644 --- a/static/js/update_mindmap.js +++ b/static/js/update_mindmap.js @@ -547,17 +547,20 @@ function enhanceMindmap() { cy.layout({ name: 'cose', animate: true, - animationDuration: 1800, + animationDuration: 2000, nodeDimensionsIncludeLabels: true, padding: 100, - spacingFactor: 1.8, - randomize: false, + spacingFactor: 2, + randomize: true, fit: true, - componentSpacing: 100, - nodeRepulsion: 8000, - edgeElasticity: 100, - nestingFactor: 1.2, - gravity: 80 + componentSpacing: 150, + nodeRepulsion: 10000, + edgeElasticity: 150, + nestingFactor: 1.5, + gravity: 100, + initialTemp: 1000, + coolingFactor: 0.95, + minTemp: 1 }).run(); // Neuronen-Namen mit besserer Lesbarkeit umgestalten @@ -621,33 +624,43 @@ function applyNeuralNetworkStyle(cy) { cy.style() .selector('node') .style({ - 'label': 'data(name)', - 'text-valign': 'bottom', + 'label': 'data(label)', + 'text-valign': 'center', 'text-halign': 'center', 'color': '#ffffff', - 'text-outline-width': 1.5, - 'text-outline-color': '#0a0e19', + 'text-outline-width': 2, + 'text-outline-color': 'rgba(0,0,0,0.8)', '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)', + 'font-size': 14, + 'font-weight': '500', + 'text-margin-y': 8, + 'width': 'mapData(neuronSize, 3, 10, 40, 80)', + 'height': 'mapData(neuronSize, 3, 10, 40, 80)', 'background-color': 'data(color)', - 'background-opacity': 0.85, - 'border-width': 0, + 'background-opacity': 0.9, + 'border-width': 2, + 'border-color': '#ffffff', + 'border-opacity': 0.8, 'shape': 'ellipse', - 'shadow-blur': 'mapData(neuronActivity, 0.3, 1, 5, 15)', + 'shadow-blur': 'mapData(neuronActivity, 0.3, 1, 15, 30)', 'shadow-color': 'data(color)', - 'shadow-opacity': 0.6, + 'shadow-opacity': 0.8, 'shadow-offset-x': 0, - 'shadow-offset-y': 0 + 'shadow-offset-y': 0, + 'transition-property': 'background-color, shadow-blur, shadow-opacity, background-opacity', + 'transition-duration': '0.3s', + 'transition-timing-function': 'ease-in-out' }) .selector('edge') .style({ - 'width': 'mapData(strength, 0.2, 0.8, 0.7, 2)', + 'width': 'mapData(strength, 0.2, 0.8, 1, 3)', 'curve-style': 'bezier', - 'line-color': '#8a8aaa', - 'line-opacity': 'mapData(strength, 0.2, 0.8, 0.4, 0.7)', + 'line-color': function(ele) { + const sourceColor = ele.source().data('color'); + const targetColor = ele.target().data('color'); + return `linear-gradient(to right, ${sourceColor}, ${targetColor})`; + }, + 'line-opacity': 'mapData(strength, 0.2, 0.8, 0.4, 0.8)', 'line-style': function(ele) { const strength = ele.data('strength'); if (strength <= 0.4) return 'dotted'; @@ -656,19 +669,23 @@ function applyNeuralNetworkStyle(cy) { }, 'target-arrow-shape': 'none', 'source-endpoint': '0% 50%', - 'target-endpoint': '100% 50%' + 'target-endpoint': '100% 50%', + 'transition-property': 'line-opacity, width', + 'transition-duration': '0.3s', + 'transition-timing-function': 'ease-in-out' }) .selector('node[isRoot]') .style({ - 'font-size': 12, + 'font-size': 18, 'font-weight': 'bold', - 'width': 50, - 'height': 50, + 'width': 100, + 'height': 100, 'background-color': '#6366f1', - 'shadow-blur': 20, + 'shadow-blur': 30, 'shadow-color': '#6366f1', - 'shadow-opacity': 0.8, - 'text-margin-y': 8 + 'shadow-opacity': 0.9, + 'text-margin-y': 10, + 'border-width': 3 }) .update(); } @@ -678,91 +695,111 @@ function applyNeuralNetworkStyle(cy) { * @param {Object} cy - Cytoscape-Instanz */ function startNeuralActivitySimulation(cy) { - if (window.neuralInterval) clearInterval(window.neuralInterval); - - const nodes = cy.nodes(); - const edges = cy.edges(); - let currentTime = Date.now(); - - // Neuronale Aktivität simulieren - function simulateNeuralActivity() { - currentTime = Date.now(); + if (window.neuralInterval) clearInterval(window.neuralInterval); - // Zufällige Neuronen "feuern" lassen - nodes.forEach(node => { - const data = node.data(); - const lastFired = data.lastFired || 0; - const timeSinceLastFire = currentTime - lastFired; - - // Prüfen ob Neuron feuern kann (Refraktionsperiode) - if (timeSinceLastFire > data.refractionPeriod) { - // Zufälliges Feuern basierend auf Aktivität - if (Math.random() < data.neuronActivity * 0.1) { - fireNeuron(node, true, currentTime); - } - } - }); - } - - // Neuron feuern lassen - function fireNeuron(node, state, currentTime) { - const data = node.data(); - data.lastFired = currentTime; + const nodes = cy.nodes(); + const edges = cy.edges(); + let currentTime = Date.now(); - // Visuelles Feedback - node.style({ - 'background-opacity': 1, - 'shadow-blur': 25, - 'shadow-opacity': 0.9 - }); - - // Nach kurzer Zeit zurück zum Normalzustand - setTimeout(() => { - node.style({ - 'background-opacity': 0.85, - 'shadow-blur': 18, - 'shadow-opacity': 0.6 - }); - }, 200); - - // Signal weiterleiten - if (state) { - propagateSignal(node, currentTime); - } - } - - // Signal über Kanten weiterleiten - function propagateSignal(sourceNode, currentTime) { - const outgoingEdges = sourceNode.connectedEdges('out'); - - outgoingEdges.forEach(edge => { - const targetNode = edge.target(); - const edgeData = edge.data(); - const latency = edgeData.latency; - - // Signal mit Verzögerung weiterleiten - setTimeout(() => { - const targetData = targetNode.data(); - const timeSinceLastFire = currentTime - (targetData.lastFired || 0); + function simulateNeuralActivity() { + currentTime = Date.now(); - // Prüfen ob Zielneuron feuern kann - if (timeSinceLastFire > targetData.refractionPeriod) { - // Signalstärke berechnen - const signalStrength = edgeData.strength * - edgeData.conductionVelocity * - sourceNode.data('neuronActivity'); - - // Neuron feuern lassen wenn Signal stark genug - if (signalStrength > targetData.threshold) { - fireNeuron(targetNode, true, currentTime + latency); - } + nodes.forEach(node => { + const data = node.data(); + const lastFired = data.lastFired || 0; + const timeSinceLastFire = currentTime - lastFired; + + if (timeSinceLastFire > data.refractionPeriod) { + if (Math.random() < data.neuronActivity * 0.15) { + fireNeuron(node, true, currentTime); + } + } + }); + } + + function fireNeuron(node, state, currentTime) { + const data = node.data(); + data.lastFired = currentTime; + + // Verbesserte visuelle Effekte + node.animate({ + style: { + 'background-opacity': 1, + 'shadow-blur': 35, + 'shadow-opacity': 1, + 'border-width': 3, + 'border-color': '#ffffff' + }, + duration: 200, + easing: 'ease-in-out-cubic' + }); + + setTimeout(() => { + node.animate({ + style: { + 'background-opacity': 0.9, + 'shadow-blur': 20, + 'shadow-opacity': 0.8, + 'border-width': 2, + 'border-color': 'rgba(255,255,255,0.8)' + }, + duration: 300, + easing: 'ease-out-cubic' + }); + }, 200); + + if (state) { + propagateSignal(node, currentTime); } - }, latency); - }); - } - - // Simulation starten - window.neuralInterval = setInterval(simulateNeuralActivity, 100); + } + + function propagateSignal(sourceNode, currentTime) { + const outgoingEdges = sourceNode.connectedEdges('out'); + + outgoingEdges.forEach(edge => { + const targetNode = edge.target(); + const edgeData = edge.data(); + const latency = edgeData.latency; + + // Verbesserte Kanten-Animation + edge.animate({ + style: { + 'line-opacity': 1, + 'width': edgeData.strength * 4 + }, + duration: 200, + easing: 'ease-in-out-cubic' + }); + + setTimeout(() => { + edge.animate({ + style: { + 'line-opacity': edgeData.strength * 0.8, + 'width': edgeData.strength * 2 + }, + duration: 300, + easing: 'ease-out-cubic' + }); + }, 200); + + setTimeout(() => { + const targetData = targetNode.data(); + const timeSinceLastFire = currentTime - (targetData.lastFired || 0); + + if (timeSinceLastFire > targetData.refractionPeriod) { + const signalStrength = edgeData.strength * + edgeData.conductionVelocity * + sourceNode.data('neuronActivity'); + + if (signalStrength > targetData.threshold) { + fireNeuron(targetNode, true, currentTime + latency); + } + } + }, latency); + }); + } + + window.neuralInterval = setInterval(simulateNeuralActivity, 100); } // Hilfe-Funktion zum Hinzufügen eines Flash-Hinweises diff --git a/static/neural-network-background-full.js b/static/neural-network-background-full.js index 7c7ecab..bc0fedb 100644 --- a/static/neural-network-background-full.js +++ b/static/neural-network-background-full.js @@ -1106,4 +1106,64 @@ window.addEventListener('beforeunload', () => { if (window.neuralNetworkBackground) { window.neuralNetworkBackground.destroy(); } -}); \ No newline at end of file +}); + +function applyNeuralNetworkStyle(cy) { + cy.style() + .selector('node') + .style({ + 'label': 'data(label)', + 'text-valign': 'center', + 'text-halign': 'center', + 'color': '#ffffff', + 'text-outline-width': 2, + 'text-outline-color': 'rgba(0,0,0,0.8)', + 'text-outline-opacity': 0.9, + 'font-size': 14, + 'font-weight': '500', + 'text-margin-y': 8, + 'width': function(ele) { + return ele.data('neuronSize') ? ele.data('neuronSize') * 8 : 60; + }, + 'height': function(ele) { + return ele.data('neuronSize') ? ele.data('neuronSize') * 8 : 60; + }, + 'background-color': 'data(color)', + 'background-opacity': 0.9, + 'border-width': 2, + 'border-color': '#ffffff', + 'border-opacity': 0.8, + 'shape': 'ellipse', + 'transition-property': 'background-color, background-opacity, border-width', + 'transition-duration': '0.3s', + 'transition-timing-function': 'ease-in-out' + }) + .selector('edge') + .style({ + 'width': function(ele) { + return ele.data('strength') ? ele.data('strength') * 3 : 1; + }, + 'curve-style': 'bezier', + 'line-color': function(ele) { + const sourceColor = ele.source().data('color'); + return sourceColor || '#8a8aaa'; + }, + 'line-opacity': function(ele) { + return ele.data('strength') ? ele.data('strength') * 0.8 : 0.4; + }, + 'line-style': function(ele) { + const strength = ele.data('strength'); + if (!strength) return 'solid'; + 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%', + 'transition-property': 'line-opacity, width', + 'transition-duration': '0.3s', + 'transition-timing-function': 'ease-in-out' + }) + .update(); +} \ No newline at end of file