From 4f6aea8e207e299cb2076d8446bf411bba316489 Mon Sep 17 00:00:00 2001 From: Till Tomczak Date: Sun, 27 Apr 2025 17:57:04 +0200 Subject: [PATCH] Update neural network background animation: Enhance color visibility and node dynamics for improved visual effects. Introduce clustering for node positioning and optimize connection rendering with increased opacity and strength. Remove old database file and update systades.db for better data management. --- database/systades.db | Bin 106496 -> 106496 bytes static/neural-network-background.js | 314 ++++++++++++++++++++-------- website/database/systades.db | Bin 106496 -> 0 bytes 3 files changed, 228 insertions(+), 86 deletions(-) delete mode 100644 website/database/systades.db diff --git a/database/systades.db b/database/systades.db index d39f948cde8cf0dac5db0538b8a4799190623f6c..7c7d3e5b1cf33ae2ee130ebc7b92ac85bcdccc89 100644 GIT binary patch delta 43 zcmZoTz}9epZGtqT$wV1vMw5*RK5~4fR)%I)CWd;3=9UKL7R|flw(pW-bZZ0v8Waq$ delta 43 zcmZoTz}9epZGtqT@kAMCM&peMK5~4o#lCZ>9ph87maX3e|gw(pW-bZZ0v8cYne diff --git a/static/neural-network-background.js b/static/neural-network-background.js index 11c3afa..b1b0521 100644 --- a/static/neural-network-background.js +++ b/static/neural-network-background.js @@ -49,35 +49,37 @@ class NeuralNetworkBackground { this.animationFrameId = null; this.isDarkMode = true; // Always use dark mode for the background - // Colors - Updated to be more subtle + // Colors - Updated for intense visibility and neural effect this.darkModeColors = { - background: '#050a14', // Darker blue-black background - nodeColor: '#4a5568', // Darker nodes for subtlety - nodePulse: '#718096', // Subtle blue pulse - connectionColor: '#2d3748', // Darker connections - flowColor: '#4a88ff80' // Semi-transparent flow highlight + background: '#030610', // Noch dunklerer Hintergrund für besseren Kontrast + nodeColor: '#88a5ff', // Hellere, leuchtende Knoten + nodePulse: '#c0d5ff', // Strahlend helles Pulsieren + connectionColor: '#5a6ca8', // Hellere, sichtbarere Verbindungen + flowColor: '#90c8ffee' // Sehr leuchtende, fast undurchsichtige Flüsse }; this.lightModeColors = { background: '#f9fafb', - nodeColor: '#7c3aed', - nodePulse: '#8b5cf6', - connectionColor: '#a78bfa', - flowColor: '#c4b5fd' + nodeColor: '#8c4aff', + nodePulse: '#ab7cff', + connectionColor: '#b798ff', + flowColor: '#d4c5ff' }; - // Config - Updated to be more subtle, efficient, and elegant + // Config - Drastisch verstärkt für strahlende Animationen und neuronale Vernetzung this.config = { - nodeCount: 70, // Reduced node count for better performance - nodeSize: 0.6, // Smaller nodes for subtlety - nodeVariation: 0.3, // Less variation for uniformity - connectionDistance: 150, // Shorter connections for cleaner look - connectionOpacity: 0.15, // More subtle connections - animationSpeed: 0.04, // Slower, more elegant movement - pulseSpeed: 0.002, // Very slow pulse for subtlety - flowSpeed: 0.4, // Slower flow animations - flowDensity: 0.0008, // Less frequent flow animations - flowLength: 0.15 // Shorter flow animations + nodeCount: 120, // Viel mehr Knoten für ein dichtes Netzwerk + nodeSize: 1.4, // Größere Knoten für mehr Sichtbarkeit + nodeVariation: 0.6, // Mehr Variation für organisches Aussehen + connectionDistance: 220, // Deutlich längere Verbindungen für mehr Vernetzung + connectionOpacity: 0.4, // Wesentlich stärkere Verbindungen + animationSpeed: 0.08, // Schnellere Bewegung + pulseSpeed: 0.006, // Schnelleres Pulsieren für lebendiges Aussehen + flowSpeed: 0.8, // Schnellere Flussanimationen + flowDensity: 0.005, // Viel mehr Flussanimationen + flowLength: 0.25, // Längere Flussanimationen + maxConnections: 6, // NEW: Neue Eigenschaft für mehr neuronale Verbindungen pro Knoten + clusteringFactor: 0.3 // NEW: Erzeugt Cluster wie in einem neuronalen Netzwerk }; // Initialize @@ -221,18 +223,60 @@ class NeuralNetworkBackground { const width = this.canvas.width / (window.devicePixelRatio || 1); const height = this.canvas.height / (window.devicePixelRatio || 1); - // Create nodes with random positions and properties - for (let i = 0; i < this.config.nodeCount; i++) { - const node = { + // Erstelle Cluster-Zentren für neuronale Netzwerkmuster + const clusterCount = Math.floor(5 + Math.random() * 4); // 5-8 Cluster + const clusters = []; + + for (let i = 0; i < clusterCount; i++) { + clusters.push({ x: Math.random() * width, y: Math.random() * height, - size: this.config.nodeSize + Math.random() * this.config.nodeVariation, + radius: 100 + Math.random() * 150 + }); + } + + // Create nodes with random positions and properties + for (let i = 0; i < this.config.nodeCount; i++) { + // Entscheide, ob dieser Knoten zu einem Cluster gehört oder nicht + const useCluster = Math.random() < this.config.clusteringFactor; + let x, y; + + if (useCluster && clusters.length > 0) { + // Wähle ein zufälliges Cluster + const cluster = clusters[Math.floor(Math.random() * clusters.length)]; + const angle = Math.random() * Math.PI * 2; + const distance = Math.random() * cluster.radius; + + // Platziere in der Nähe des Clusters mit einiger Streuung + x = cluster.x + Math.cos(angle) * distance; + y = cluster.y + Math.sin(angle) * distance; + + // Stelle sicher, dass es innerhalb des Bildschirms bleibt + x = Math.max(0, Math.min(width, x)); + y = Math.max(0, Math.min(height, y)); + } else { + // Zufällige Position außerhalb von Clustern + x = Math.random() * width; + y = Math.random() * height; + } + + // Bestimme die Knotengröße - wichtigere Knoten (in Clustern) sind größer + const nodeImportance = useCluster ? 1.2 : 0.8; + const size = this.config.nodeSize * nodeImportance + Math.random() * this.config.nodeVariation; + + const node = { + x: x, + y: y, + size: size, speed: { x: (Math.random() - 0.5) * this.config.animationSpeed, y: (Math.random() - 0.5) * this.config.animationSpeed }, pulsePhase: Math.random() * Math.PI * 2, // Random starting phase - connections: [] + connections: [], + isActive: Math.random() < 0.3, // Some nodes start active for neural firing effect + lastFired: 0, // For neural firing animation + firingRate: 1000 + Math.random() * 4000 // Random firing rate in ms }; this.nodes.push(node); @@ -248,23 +292,60 @@ class NeuralNetworkBackground { const nodeA = this.nodes[i]; nodeA.connections = []; - for (let j = i + 1; j < this.nodes.length; j++) { + // Sortiere andere Knoten nach Entfernung für bevorzugte nahe Verbindungen + const potentialConnections = []; + + for (let j = 0; j < this.nodes.length; j++) { + if (i === j) continue; + const nodeB = this.nodes[j]; const dx = nodeB.x - nodeA.x; const dy = nodeB.y - nodeA.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < this.config.connectionDistance) { + potentialConnections.push({ + index: j, + distance: distance + }); + } + } + + // Sortiere nach Entfernung + potentialConnections.sort((a, b) => a.distance - b.distance); + + // Wähle die nächsten N Verbindungen, maximal maxConnections + const maxConn = Math.min( + this.config.maxConnections, + potentialConnections.length, + 1 + Math.floor(Math.random() * this.config.maxConnections) + ); + + for (let c = 0; c < maxConn; c++) { + const connection = potentialConnections[c]; + const j = connection.index; + const nodeB = this.nodes[j]; + const distance = connection.distance; + + // Create weighted connection (closer = stronger) + const connectionStrength = Math.max(0, 1 - distance / this.config.connectionDistance); + const connOpacity = connectionStrength * this.config.connectionOpacity; + + // Check if connection already exists + if (!this.connections.some(conn => + (conn.from === i && conn.to === j) || (conn.from === j && conn.to === i) + )) { // Create connection - const connection = { + this.connections.push({ from: i, to: j, distance: distance, - opacity: Math.max(0, 1 - distance / this.config.connectionDistance) * this.config.connectionOpacity, - hasFlow: false // Each connection can have a flow - }; + opacity: connOpacity, + strength: connectionStrength, + hasFlow: false, // Each connection can have a flow + lastActivated: 0 // For neural firing animation + }); - this.connections.push(connection); nodeA.connections.push(j); nodeB.connections.push(i); } @@ -280,42 +361,48 @@ class NeuralNetworkBackground { // Update nodes const width = this.canvas.width / (window.devicePixelRatio || 1); const height = this.canvas.height / (window.devicePixelRatio || 1); + const now = Date.now(); - // Update node positions - slower, more flowing movement + // Simulate neural firing for (let i = 0; i < this.nodes.length; i++) { const node = this.nodes[i]; - // Move node with slight randomness for organic feel - node.speed.x += (Math.random() - 0.5) * 0.001; - node.speed.y += (Math.random() - 0.5) * 0.001; - - // Dampen speeds for stability - node.speed.x *= 0.99; - node.speed.y *= 0.99; - - // Apply speed limits - node.speed.x = Math.max(-this.config.animationSpeed, Math.min(this.config.animationSpeed, node.speed.x)); - node.speed.y = Math.max(-this.config.animationSpeed, Math.min(this.config.animationSpeed, node.speed.y)); - - // Move node - node.x += node.speed.x; - node.y += node.speed.y; - - // Boundary check with smooth bounce - if (node.x < 0 || node.x > width) { - node.speed.x *= -0.8; // Softer bounce - node.x = Math.max(0, Math.min(node.x, width)); - } - - if (node.y < 0 || node.y > height) { - node.speed.y *= -0.8; // Softer bounce - node.y = Math.max(0, Math.min(node.y, height)); - } - - // Update pulse phase - node.pulsePhase += this.config.pulseSpeed; - if (node.pulsePhase > Math.PI * 2) { - node.pulsePhase -= Math.PI * 2; + // Check if node should fire based on its firing rate + if (now - node.lastFired > node.firingRate) { + node.isActive = true; + node.lastFired = now; + + // Activate connected nodes with probability based on connection strength + for (const connIndex of node.connections) { + // Find the connection + const conn = this.connections.find(c => + (c.from === i && c.to === connIndex) || (c.from === connIndex && c.to === i) + ); + + if (conn) { + // Mark connection as recently activated + conn.lastActivated = now; + + // Create a flow along this connection + if (Math.random() < conn.strength * 0.8) { + this.flows.push({ + connection: conn, + progress: 0, + direction: conn.from === i, // Flow from activated node + length: this.config.flowLength + Math.random() * 0.1, + intensity: 0.7 + Math.random() * 0.3 // Random intensity for variation + }); + } + + // Probability for connected node to activate + if (Math.random() < conn.strength * 0.5) { + this.nodes[connIndex].isActive = true; + this.nodes[connIndex].lastFired = now - Math.random() * 500; // Slight variation + } + } + } + } else if (now - node.lastFired > 300) { // Deactivate after short period + node.isActive = false; } } @@ -355,6 +442,11 @@ class NeuralNetworkBackground { this.flows.splice(i, 1); } } + + // Generate more flows for enhanced visibility + if (Math.random() < this.config.flowDensity * 2) { + this.createNewFlow(); + } } // New method to create flow animations @@ -416,14 +508,30 @@ class NeuralNetworkBackground { const positions = new Float32Array(this.nodes.length * 2); const sizes = new Float32Array(this.nodes.length); + const now = Date.now(); + for (let i = 0; i < this.nodes.length; i++) { const node = this.nodes[i]; positions[i * 2] = node.x; positions[i * 2 + 1] = node.y; - // Size with subtle pulse effect - const pulse = Math.sin(node.pulsePhase) * 0.2 + 1; - sizes[i] = node.size * pulse * (node.connections.length > 3 ? 1.3 : 1); + // Enhanced pulse effect with additional boost for active nodes + let pulse = Math.sin(node.pulsePhase) * 0.4 + 1; + + // Make active nodes pulse more intensely (neural firing effect) + if (node.isActive) { + const timeSinceFired = now - node.lastFired; + if (timeSinceFired < 300) { + // Quick expand then contract effect + const normalizedTime = timeSinceFired / 300; + const fireBoost = 1.5 * (1 - normalizedTime); + pulse += fireBoost; + } + } + + // Nodes with more connections are larger (hub neurons) + const connectivityFactor = 1 + (node.connections.length / this.config.maxConnections) * 0.8; + sizes[i] = node.size * pulse * connectivityFactor; } // Bind position buffer @@ -452,24 +560,45 @@ class NeuralNetworkBackground { ); this.gl.enableVertexAttribArray(this.programInfo.attribLocations.pointSize); - // Set node color - more subtle - const colorObj = this.isDarkMode ? this.darkModeColors : this.lightModeColors; - const nodeColor = this.hexToRgb(colorObj.nodeColor); - this.gl.uniform4f( - this.programInfo.uniformLocations.color, - nodeColor.r / 255, - nodeColor.g / 255, - nodeColor.b / 255, - 0.7 // Lower opacity for subtlety - ); - - // Draw nodes + // Enable blending for all nodes this.gl.enable(this.gl.BLEND); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); // Additive blending for glow - this.gl.drawArrays(this.gl.POINTS, 0, this.nodes.length); + + // Draw each node individually with its own color + for (let i = 0; i < this.nodes.length; i++) { + const node = this.nodes[i]; + + // Set node color - more visible with active highlighting + const colorObj = this.isDarkMode ? this.darkModeColors : this.lightModeColors; + const nodeColor = this.hexToRgb(colorObj.nodeColor); + const nodePulseColor = this.hexToRgb(colorObj.nodePulse); + + // Use pulse color for active nodes + let r = nodeColor.r / 255; + let g = nodeColor.g / 255; + let b = nodeColor.b / 255; + + // Active nodes get brighter color + if (node.isActive) { + r = (r + nodePulseColor.r / 255) / 2; + g = (g + nodePulseColor.g / 255) / 2; + b = (b + nodePulseColor.b / 255) / 2; + } + + this.gl.uniform4f( + this.programInfo.uniformLocations.color, + r, g, b, + 0.95 // Higher opacity for maximum visibility + ); + + // Draw each node individually for better control + this.gl.drawArrays(this.gl.POINTS, i, 1); + } } renderConnectionsWebGL() { + const now = Date.now(); + // For each connection, draw a line for (const connection of this.connections) { const fromNode = this.nodes[connection.from]; @@ -497,15 +626,28 @@ class NeuralNetworkBackground { // Disable point size attribute for lines this.gl.disableVertexAttribArray(this.programInfo.attribLocations.pointSize); - // Set line color with connection opacity - darker, more subtle + // Set line color with connection opacity const colorObj = this.isDarkMode ? this.darkModeColors : this.lightModeColors; - const lineColor = this.hexToRgb(colorObj.connectionColor); + let lineColor = this.hexToRgb(colorObj.connectionColor); + + // Highlight recently activated connections for neural pathway effect + let opacity = connection.opacity * 1.4; // Base increased visibility + + if (now - connection.lastActivated < 800) { + // Make recently activated connections brighter + lineColor = this.hexToRgb(colorObj.flowColor); + + // Fade out effect + const timeFactor = 1 - ((now - connection.lastActivated) / 800); + opacity = Math.max(opacity, timeFactor * 0.9); + } + this.gl.uniform4f( this.programInfo.uniformLocations.color, lineColor.r / 255, lineColor.g / 255, lineColor.b / 255, - connection.opacity * 0.8 // Reduced for subtlety + opacity ); // Draw the line @@ -585,7 +727,7 @@ class NeuralNetworkBackground { 1 ); - // Flow color - subtle glow + // Flow color - much stronger glow const colorObj = this.isDarkMode ? this.darkModeColors : this.lightModeColors; const flowColor = this.hexToRgb(colorObj.flowColor); this.gl.uniform4f( @@ -593,13 +735,13 @@ class NeuralNetworkBackground { flowColor.r / 255, flowColor.g / 255, flowColor.b / 255, - 0.4 * fadeOpacity // Subtle flow opacity + 0.9 * fadeOpacity * flow.intensity // Much stronger flow opacity with intensity variation ); // Draw the flow line this.gl.enable(this.gl.BLEND); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); - this.gl.lineWidth(1.5); // Slightly thicker for visibility + this.gl.lineWidth(2.5); // Even thicker for dramatic visibility this.gl.drawArrays(this.gl.LINES, 0, 2); } } diff --git a/website/database/systades.db b/website/database/systades.db deleted file mode 100644 index 7ceb056e9a8d3b15016a52e12636ce1969f19b29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106496 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 z