-
Notifications
You must be signed in to change notification settings - Fork 44
Open
Description
OK explore something a little more unique for the default controller theme. Alex has vibe coded some animations, and we should explore possibly implementing something like this.
Heres a video
Dynamic.Theme.Behavior.mov
Some high level questions I have. Is this too computationally intensive? is there a light weight way we could replace the default controller theme with something like this?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Diamond Stars Header</title>
<style>
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #000000;
font-family: Arial, sans-serif;
}
.header-container {
width: 400px;
height: 120px;
background-color: #181818;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
position: relative;
}
.gradient-fade {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
background: linear-gradient(to bottom, transparent, #181818);
z-index: 5;
}
.star {
position: absolute;
background-color: #FFD700;
transform: rotate(45deg);
}
.star.foreground {
box-shadow: 0 0 6px rgba(255, 215, 0, 0.7);
}
.star.middle {
box-shadow: 0 0 4px rgba(255, 215, 0, 0.5);
}
.star.background {
box-shadow: 0 0 2px rgba(255, 215, 0, 0.3);
}
</style>
</head>
<body>
<div class="header-container" id="header-container">
<div id="starfield"></div>
<div class="gradient-fade"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Fixed dimensions - these won't change
const HEADER_WIDTH = 400;
const HEADER_HEIGHT = 120;
const container = document.getElementById('header-container');
const starfield = document.getElementById('starfield');
// Star settings
const starCount = 120;
const stars = [];
// Mouse tracking
let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
let containerRect = container.getBoundingClientRect();
document.addEventListener('mousemove', function(e) {
mouseX = e.clientX;
mouseY = e.clientY;
});
// Create all stars and add them to the DOM
function createStars() {
// Layer distribution
const foregroundCount = Math.round(starCount * 0.15);
const middleCount = Math.round(starCount * 0.25);
const backgroundCount = starCount - foregroundCount - middleCount;
// Create foreground stars (15%)
for (let i = 0; i < foregroundCount; i++) {
createStarInLayer('foreground', 2.0, 3.5, 0.7, 1.0, 0.4);
}
// Create middle stars (25%)
for (let i = 0; i < middleCount; i++) {
createStarInLayer('middle', 1.2, 2.2, 0.5, 0.8, 0.25);
}
// Create background stars (60%)
for (let i = 0; i < backgroundCount; i++) {
createStarInLayer('background', 0.5, 1.3, 0.3, 0.5, 0.12);
}
}
// Helper to create a star in a specific layer
function createStarInLayer(layerClass, minSize, maxSize, minOpacity, maxOpacity, maxSpeed) {
// Generate random size and opacity
const size = minSize + Math.random() * (maxSize - minSize);
const opacity = minOpacity + Math.random() * (maxOpacity - minOpacity);
const speed = 0.1 + Math.random() * maxSpeed;
// Create the DOM element
const element = document.createElement('div');
element.className = `star ${layerClass}`;
element.style.width = `${size}px`;
element.style.height = `${size}px`;
element.style.opacity = opacity;
// Position the star randomly within the header bounds
const xPos = Math.random() * HEADER_WIDTH;
const yPos = Math.random() * HEADER_HEIGHT;
element.style.left = `${xPos}px`;
element.style.top = `${yPos}px`;
starfield.appendChild(element);
// Add to the stars array
stars.push({
element,
x: xPos,
y: yPos,
size,
speed,
layer: layerClass,
dx: 0,
dy: 0
});
}
// Animation loop
function animate() {
// Get the center of the header
const headerCenterX = containerRect.left + HEADER_WIDTH / 2;
const headerCenterY = containerRect.top + HEADER_HEIGHT / 2;
// Calculate the vector from center to mouse
const dx = mouseX - headerCenterX;
const dy = mouseY - headerCenterY;
const dist = Math.sqrt(dx * dx + dy * dy);
// Calculate influence based on distance
const maxDist = Math.max(window.innerWidth, window.innerHeight) / 3;
let influence = Math.max(0, 1 - dist / maxDist);
influence = Math.pow(influence, 0.5);
// Target movement direction
const targetX = (dist > 0.1) ? (dx / dist) * influence : 0;
const targetY = (dist > 0.1) ? (dy / dist) * influence * 0.5 : 0;
// Update each star
stars.forEach(star => {
// Different easing based on layer
const ease = (star.layer === 'foreground') ? 0.04 :
(star.layer === 'middle') ? 0.02 : 0.01;
// Ease toward target direction
star.dx += (targetX - star.dx) * ease;
star.dy += (targetY - star.dy) * ease;
// Apply movement
star.x += star.dx * star.speed;
star.y += star.dy * star.speed;
// Wrap around edges
if (star.x < -5) star.x = HEADER_WIDTH + 5;
else if (star.x > HEADER_WIDTH + 5) star.x = -5;
if (star.y < -5) star.y = HEADER_HEIGHT + 5;
else if (star.y > HEADER_HEIGHT + 5) star.y = -5;
// Update DOM element position
star.element.style.left = `${star.x}px`;
star.element.style.top = `${star.y}px`;
});
// Continue animation
requestAnimationFrame(animate);
}
// Initialize everything
function init() {
createStars();
containerRect = container.getBoundingClientRect();
requestAnimationFrame(animate);
}
// Update container position on resize
window.addEventListener('resize', function() {
containerRect = container.getBoundingClientRect();
});
// Start everything
init();
});
</script>
</body>
</html>
It may turn out that this is too computationally intensive, maybe not, lets explore what it would mean to implement it. If that turns out to be the case, are there improvements we could make to the animation?
Let me know how it goes!
Reactions are currently unavailable