Compare commits

...

2 Commits

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 // Activate connected nodes with probability based on connection strength
node.speed.x *= 0.99; for (const connIndex of node.connections) {
node.speed.y *= 0.99; // Find the connection
const conn = this.connections.find(c =>
(c.from === i && c.to === connIndex) || (c.from === connIndex && c.to === i)
);
// Apply speed limits if (conn) {
node.speed.x = Math.max(-this.config.animationSpeed, Math.min(this.config.animationSpeed, node.speed.x)); // Mark connection as recently activated
node.speed.y = Math.max(-this.config.animationSpeed, Math.min(this.config.animationSpeed, node.speed.y)); conn.lastActivated = now;
// Move node // Create a flow along this connection
node.x += node.speed.x; if (Math.random() < conn.strength * 0.8) {
node.y += node.speed.y; this.flows.push({
connection: conn,
// Boundary check with smooth bounce progress: 0,
if (node.x < 0 || node.x > width) { direction: conn.from === i, // Flow from activated node
node.speed.x *= -0.8; // Softer bounce length: this.config.flowLength + Math.random() * 0.1,
node.x = Math.max(0, Math.min(node.x, width)); intensity: 0.7 + Math.random() * 0.3 // Random intensity for variation
});
} }
if (node.y < 0 || node.y > height) { // Probability for connected node to activate
node.speed.y *= -0.8; // Softer bounce if (Math.random() < conn.strength * 0.5) {
node.y = Math.max(0, Math.min(node.y, height)); this.nodes[connIndex].isActive = true;
this.nodes[connIndex].lastFired = now - Math.random() * 500; // Slight variation
} }
}
// Update pulse phase }
node.pulsePhase += this.config.pulseSpeed; } else if (now - node.lastFired > 300) { // Deactivate after short period
if (node.pulsePhase > Math.PI * 2) { node.isActive = false;
node.pulsePhase -= Math.PI * 2;
} }
} }
@@ -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.