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.

This commit is contained in:
2025-04-27 17:57:04 +02:00
parent e5f485d9d7
commit 4f6aea8e20
3 changed files with 228 additions and 86 deletions

Binary file not shown.

View File

@@ -49,35 +49,37 @@ class NeuralNetworkBackground {
this.animationFrameId = null; this.animationFrameId = null;
this.isDarkMode = true; // Always use dark mode for the background 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 = { this.darkModeColors = {
background: '#050a14', // Darker blue-black background background: '#030610', // Noch dunklerer Hintergrund für besseren Kontrast
nodeColor: '#4a5568', // Darker nodes for subtlety nodeColor: '#88a5ff', // Hellere, leuchtende Knoten
nodePulse: '#718096', // Subtle blue pulse nodePulse: '#c0d5ff', // Strahlend helles Pulsieren
connectionColor: '#2d3748', // Darker connections connectionColor: '#5a6ca8', // Hellere, sichtbarere Verbindungen
flowColor: '#4a88ff80' // Semi-transparent flow highlight flowColor: '#90c8ffee' // Sehr leuchtende, fast undurchsichtige Flüsse
}; };
this.lightModeColors = { this.lightModeColors = {
background: '#f9fafb', background: '#f9fafb',
nodeColor: '#7c3aed', nodeColor: '#8c4aff',
nodePulse: '#8b5cf6', nodePulse: '#ab7cff',
connectionColor: '#a78bfa', connectionColor: '#b798ff',
flowColor: '#c4b5fd' flowColor: '#d4c5ff'
}; };
// Config - Updated to be more subtle, efficient, and elegant // Config - Drastisch verstärkt für strahlende Animationen und neuronale Vernetzung
this.config = { this.config = {
nodeCount: 70, // Reduced node count for better performance nodeCount: 120, // Viel mehr Knoten für ein dichtes Netzwerk
nodeSize: 0.6, // Smaller nodes for subtlety nodeSize: 1.4, // Größere Knoten für mehr Sichtbarkeit
nodeVariation: 0.3, // Less variation for uniformity nodeVariation: 0.6, // Mehr Variation für organisches Aussehen
connectionDistance: 150, // Shorter connections for cleaner look connectionDistance: 220, // Deutlich längere Verbindungen für mehr Vernetzung
connectionOpacity: 0.15, // More subtle connections connectionOpacity: 0.4, // Wesentlich stärkere Verbindungen
animationSpeed: 0.04, // Slower, more elegant movement animationSpeed: 0.08, // Schnellere Bewegung
pulseSpeed: 0.002, // Very slow pulse for subtlety pulseSpeed: 0.006, // Schnelleres Pulsieren für lebendiges Aussehen
flowSpeed: 0.4, // Slower flow animations flowSpeed: 0.8, // Schnellere Flussanimationen
flowDensity: 0.0008, // Less frequent flow animations flowDensity: 0.005, // Viel mehr Flussanimationen
flowLength: 0.15 // Shorter flow animations 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 // Initialize
@@ -221,18 +223,60 @@ class NeuralNetworkBackground {
const width = this.canvas.width / (window.devicePixelRatio || 1); const width = this.canvas.width / (window.devicePixelRatio || 1);
const height = this.canvas.height / (window.devicePixelRatio || 1); const height = this.canvas.height / (window.devicePixelRatio || 1);
// Create nodes with random positions and properties // Erstelle Cluster-Zentren für neuronale Netzwerkmuster
for (let i = 0; i < this.config.nodeCount; i++) { const clusterCount = Math.floor(5 + Math.random() * 4); // 5-8 Cluster
const node = { const clusters = [];
for (let i = 0; i < clusterCount; i++) {
clusters.push({
x: Math.random() * width, x: Math.random() * width,
y: Math.random() * height, 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: { speed: {
x: (Math.random() - 0.5) * this.config.animationSpeed, x: (Math.random() - 0.5) * this.config.animationSpeed,
y: (Math.random() - 0.5) * this.config.animationSpeed y: (Math.random() - 0.5) * this.config.animationSpeed
}, },
pulsePhase: Math.random() * Math.PI * 2, // Random starting phase 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); this.nodes.push(node);
@@ -248,23 +292,60 @@ class NeuralNetworkBackground {
const nodeA = this.nodes[i]; const nodeA = this.nodes[i];
nodeA.connections = []; 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 nodeB = this.nodes[j];
const dx = nodeB.x - nodeA.x; const dx = nodeB.x - nodeA.x;
const dy = nodeB.y - nodeA.y; const dy = nodeB.y - nodeA.y;
const distance = Math.sqrt(dx * dx + dy * dy); const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.config.connectionDistance) { 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 // Create connection
const connection = { this.connections.push({
from: i, from: i,
to: j, to: j,
distance: distance, distance: distance,
opacity: Math.max(0, 1 - distance / this.config.connectionDistance) * this.config.connectionOpacity, opacity: connOpacity,
hasFlow: false // Each connection can have a flow strength: connectionStrength,
}; hasFlow: false, // Each connection can have a flow
lastActivated: 0 // For neural firing animation
});
this.connections.push(connection);
nodeA.connections.push(j); nodeA.connections.push(j);
nodeB.connections.push(i); nodeB.connections.push(i);
} }
@@ -280,42 +361,48 @@ class NeuralNetworkBackground {
// Update nodes // Update nodes
const width = this.canvas.width / (window.devicePixelRatio || 1); const width = this.canvas.width / (window.devicePixelRatio || 1);
const height = this.canvas.height / (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++) { for (let i = 0; i < this.nodes.length; i++) {
const node = this.nodes[i]; const node = this.nodes[i];
// Move node with slight randomness for organic feel // Check if node should fire based on its firing rate
node.speed.x += (Math.random() - 0.5) * 0.001; if (now - node.lastFired > node.firingRate) {
node.speed.y += (Math.random() - 0.5) * 0.001; node.isActive = true;
node.lastFired = now;
// Dampen speeds for stability
node.speed.x *= 0.99; // Activate connected nodes with probability based on connection strength
node.speed.y *= 0.99; for (const connIndex of node.connections) {
// Find the connection
// Apply speed limits const conn = this.connections.find(c =>
node.speed.x = Math.max(-this.config.animationSpeed, Math.min(this.config.animationSpeed, node.speed.x)); (c.from === i && c.to === connIndex) || (c.from === connIndex && c.to === i)
node.speed.y = Math.max(-this.config.animationSpeed, Math.min(this.config.animationSpeed, node.speed.y)); );
// Move node if (conn) {
node.x += node.speed.x; // Mark connection as recently activated
node.y += node.speed.y; conn.lastActivated = now;
// Boundary check with smooth bounce // Create a flow along this connection
if (node.x < 0 || node.x > width) { if (Math.random() < conn.strength * 0.8) {
node.speed.x *= -0.8; // Softer bounce this.flows.push({
node.x = Math.max(0, Math.min(node.x, width)); connection: conn,
} progress: 0,
direction: conn.from === i, // Flow from activated node
if (node.y < 0 || node.y > height) { length: this.config.flowLength + Math.random() * 0.1,
node.speed.y *= -0.8; // Softer bounce intensity: 0.7 + Math.random() * 0.3 // Random intensity for variation
node.y = Math.max(0, Math.min(node.y, height)); });
} }
// Update pulse phase // Probability for connected node to activate
node.pulsePhase += this.config.pulseSpeed; if (Math.random() < conn.strength * 0.5) {
if (node.pulsePhase > Math.PI * 2) { this.nodes[connIndex].isActive = true;
node.pulsePhase -= Math.PI * 2; 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); 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 // New method to create flow animations
@@ -416,14 +508,30 @@ class NeuralNetworkBackground {
const positions = new Float32Array(this.nodes.length * 2); const positions = new Float32Array(this.nodes.length * 2);
const sizes = new Float32Array(this.nodes.length); const sizes = new Float32Array(this.nodes.length);
const now = Date.now();
for (let i = 0; i < this.nodes.length; i++) { for (let i = 0; i < this.nodes.length; i++) {
const node = this.nodes[i]; const node = this.nodes[i];
positions[i * 2] = node.x; positions[i * 2] = node.x;
positions[i * 2 + 1] = node.y; positions[i * 2 + 1] = node.y;
// Size with subtle pulse effect // Enhanced pulse effect with additional boost for active nodes
const pulse = Math.sin(node.pulsePhase) * 0.2 + 1; let pulse = Math.sin(node.pulsePhase) * 0.4 + 1;
sizes[i] = node.size * pulse * (node.connections.length > 3 ? 1.3 : 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 // Bind position buffer
@@ -452,24 +560,45 @@ class NeuralNetworkBackground {
); );
this.gl.enableVertexAttribArray(this.programInfo.attribLocations.pointSize); this.gl.enableVertexAttribArray(this.programInfo.attribLocations.pointSize);
// Set node color - more subtle // Enable blending for all nodes
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
this.gl.enable(this.gl.BLEND); this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); // Additive blending for glow 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() { renderConnectionsWebGL() {
const now = Date.now();
// For each connection, draw a line // For each connection, draw a line
for (const connection of this.connections) { for (const connection of this.connections) {
const fromNode = this.nodes[connection.from]; const fromNode = this.nodes[connection.from];
@@ -497,15 +626,28 @@ class NeuralNetworkBackground {
// Disable point size attribute for lines // Disable point size attribute for lines
this.gl.disableVertexAttribArray(this.programInfo.attribLocations.pointSize); 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 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.gl.uniform4f(
this.programInfo.uniformLocations.color, this.programInfo.uniformLocations.color,
lineColor.r / 255, lineColor.r / 255,
lineColor.g / 255, lineColor.g / 255,
lineColor.b / 255, lineColor.b / 255,
connection.opacity * 0.8 // Reduced for subtlety opacity
); );
// Draw the line // Draw the line
@@ -585,7 +727,7 @@ class NeuralNetworkBackground {
1 1
); );
// Flow color - subtle glow // Flow color - much stronger glow
const colorObj = this.isDarkMode ? this.darkModeColors : this.lightModeColors; const colorObj = this.isDarkMode ? this.darkModeColors : this.lightModeColors;
const flowColor = this.hexToRgb(colorObj.flowColor); const flowColor = this.hexToRgb(colorObj.flowColor);
this.gl.uniform4f( this.gl.uniform4f(
@@ -593,13 +735,13 @@ class NeuralNetworkBackground {
flowColor.r / 255, flowColor.r / 255,
flowColor.g / 255, flowColor.g / 255,
flowColor.b / 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 // Draw the flow line
this.gl.enable(this.gl.BLEND); this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); 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); this.gl.drawArrays(this.gl.LINES, 0, 2);
} }
} }

Binary file not shown.