forked from Rockachopa/Timmy-time-dashboard
Polish UI design with sleeker components and vivid magical animations (#172)
This commit is contained in:
committed by
GitHub
parent
9e56fad342
commit
0b91e45d90
@@ -13,8 +13,8 @@
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous" />
|
||||
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="stylesheet" href="/static/style.css?v=5" />
|
||||
<link rel="stylesheet" href="/static/css/mission-control.css?v=1" />
|
||||
<link rel="stylesheet" href="/static/style.css?v=6" />
|
||||
<link rel="stylesheet" href="/static/css/mission-control.css?v=2" />
|
||||
{% block extra_styles %}{% endblock %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.3/dist/htmx.min.js" crossorigin="anonymous"></script>
|
||||
<script>
|
||||
@@ -151,10 +151,113 @@
|
||||
<!-- Toast container -->
|
||||
<div class="mc-toast-container" id="toast-container"></div>
|
||||
|
||||
<!-- Magical floating particles canvas -->
|
||||
<canvas id="magic-particles" aria-hidden="true"></canvas>
|
||||
|
||||
<main class="mc-main">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<script>
|
||||
// ── Magical floating particles ──
|
||||
(function() {
|
||||
var canvas = document.getElementById('magic-particles');
|
||||
if (!canvas) return;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var particles = [];
|
||||
var PARTICLE_COUNT = 40;
|
||||
var raf;
|
||||
|
||||
function resize() {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
}
|
||||
resize();
|
||||
window.addEventListener('resize', resize);
|
||||
|
||||
var colors = [
|
||||
{ r: 168, g: 85, b: 247 }, // purple
|
||||
{ r: 124, g: 58, b: 237 }, // violet
|
||||
{ r: 192, g: 132, b: 252 }, // light purple
|
||||
{ r: 249, g: 115, b: 22 }, // orange
|
||||
{ r: 237, g: 224, b: 255 }, // white-purple
|
||||
];
|
||||
|
||||
function createParticle() {
|
||||
var c = colors[Math.floor(Math.random() * colors.length)];
|
||||
return {
|
||||
x: Math.random() * canvas.width,
|
||||
y: Math.random() * canvas.height,
|
||||
vx: (Math.random() - 0.5) * 0.3,
|
||||
vy: (Math.random() - 0.5) * 0.3,
|
||||
r: Math.random() * 2.2 + 0.5,
|
||||
alpha: Math.random() * 0.4 + 0.05,
|
||||
alphaDir: (Math.random() - 0.5) * 0.008,
|
||||
color: c,
|
||||
phase: Math.random() * Math.PI * 2,
|
||||
drift: Math.random() * 0.2 + 0.05
|
||||
};
|
||||
}
|
||||
|
||||
for (var i = 0; i < PARTICLE_COUNT; i++) {
|
||||
particles.push(createParticle());
|
||||
}
|
||||
|
||||
var time = 0;
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
time += 0.003;
|
||||
|
||||
for (var i = 0; i < particles.length; i++) {
|
||||
var p = particles[i];
|
||||
p.x += p.vx + Math.sin(time + p.phase) * p.drift;
|
||||
p.y += p.vy + Math.cos(time + p.phase) * p.drift;
|
||||
p.alpha += p.alphaDir;
|
||||
|
||||
if (p.alpha <= 0.02 || p.alpha >= 0.45) p.alphaDir *= -1;
|
||||
p.alpha = Math.max(0.02, Math.min(0.45, p.alpha));
|
||||
|
||||
if (p.x < -20) p.x = canvas.width + 20;
|
||||
if (p.x > canvas.width + 20) p.x = -20;
|
||||
if (p.y < -20) p.y = canvas.height + 20;
|
||||
if (p.y > canvas.height + 20) p.y = -20;
|
||||
|
||||
// Glow
|
||||
var grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 6);
|
||||
grad.addColorStop(0, 'rgba(' + p.color.r + ',' + p.color.g + ',' + p.color.b + ',' + (p.alpha * 0.6) + ')');
|
||||
grad.addColorStop(1, 'rgba(' + p.color.r + ',' + p.color.g + ',' + p.color.b + ',0)');
|
||||
ctx.fillStyle = grad;
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.r * 6, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Core
|
||||
ctx.fillStyle = 'rgba(' + p.color.r + ',' + p.color.g + ',' + p.color.b + ',' + p.alpha + ')';
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
raf = requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
// Only run when tab is visible
|
||||
function onVis() {
|
||||
if (document.hidden) {
|
||||
cancelAnimationFrame(raf);
|
||||
} else {
|
||||
draw();
|
||||
}
|
||||
}
|
||||
document.addEventListener('visibilitychange', onVis);
|
||||
draw();
|
||||
|
||||
// Respect reduced motion preference
|
||||
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||
cancelAnimationFrame(raf);
|
||||
canvas.style.display = 'none';
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
// Clock
|
||||
function updateClock() {
|
||||
|
||||
Reference in New Issue
Block a user