Compare commits
2 Commits
6cf9b2a627
...
8890a62026
| Author | SHA1 | Date | |
|---|---|---|---|
| 8890a62026 | |||
| 4f6aea8e20 |
Binary file not shown.
@@ -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;
|
||||
// Check if node should fire based on its firing rate
|
||||
if (now - node.lastFired > node.firingRate) {
|
||||
node.isActive = true;
|
||||
node.lastFired = now;
|
||||
|
||||
// Dampen speeds for stability
|
||||
node.speed.x *= 0.99;
|
||||
node.speed.y *= 0.99;
|
||||
// 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)
|
||||
);
|
||||
|
||||
// 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));
|
||||
if (conn) {
|
||||
// Mark connection as recently activated
|
||||
conn.lastActivated = now;
|
||||
|
||||
// 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));
|
||||
// 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
|
||||
});
|
||||
}
|
||||
|
||||
if (node.y < 0 || node.y > height) {
|
||||
node.speed.y *= -0.8; // Softer bounce
|
||||
node.y = Math.max(0, Math.min(node.y, height));
|
||||
// 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
|
||||
}
|
||||
|
||||
// Update pulse phase
|
||||
node.pulsePhase += this.config.pulseSpeed;
|
||||
if (node.pulsePhase > Math.PI * 2) {
|
||||
node.pulsePhase -= Math.PI * 2;
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user