Add a smooth, animated dot cursor that follows the mouse
Adds a custom cursor with smooth animation using JavaScript and CSS, updates card backgrounds to #0a0a0a, and increases navigation bar button margins. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 75bceff7-98f2-4f6e-ae8e-e735399a1fe8 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 20f129c4-266a-489a-9b78-af922ec1dcda Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d0a1d46d-d203-4308-bc6a-312ac7c0243b/75bceff7-98f2-4f6e-ae8e-e735399a1fe8/mApn6AR
This commit is contained in:
@@ -32,6 +32,34 @@ body {
|
||||
line-height: 1.6;
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
.dot-cursor {
|
||||
position: fixed;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #3b82f6;
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
z-index: 999999;
|
||||
transition: transform 0.15s ease, background 0.2s ease;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.dot-cursor.hover {
|
||||
transform: scale(1.5);
|
||||
background: #60a5fa;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.dot-cursor {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
body::after {
|
||||
@@ -87,7 +115,7 @@ body::after {
|
||||
|
||||
.navbar-links {
|
||||
display: flex;
|
||||
gap: 40px;
|
||||
gap: 56px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
@@ -856,7 +884,7 @@ hr {
|
||||
|
||||
.card,
|
||||
.card-sponsors {
|
||||
background: var(--gray-900);
|
||||
background: #0a0a0a;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--gray-700);
|
||||
|
||||
@@ -45,6 +45,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
ScrollTrigger.addEventListener('refresh', () => lenis.resize());
|
||||
ScrollTrigger.refresh();
|
||||
|
||||
initSmoothCursor();
|
||||
|
||||
let lastScrollTop = 0;
|
||||
const nav = document.querySelector('nav');
|
||||
|
||||
@@ -411,3 +413,60 @@ function initStars() {
|
||||
section.appendChild(starContainer);
|
||||
});
|
||||
}
|
||||
|
||||
function initSmoothCursor() {
|
||||
if (window.innerWidth <= 768) return;
|
||||
|
||||
const cursor = document.createElement('div');
|
||||
cursor.className = 'dot-cursor';
|
||||
document.body.appendChild(cursor);
|
||||
|
||||
let mouseX = 0;
|
||||
let mouseY = 0;
|
||||
let cursorX = 0;
|
||||
let cursorY = 0;
|
||||
let velocityX = 0;
|
||||
let velocityY = 0;
|
||||
|
||||
const ease = 0.15;
|
||||
const friction = 0.85;
|
||||
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
mouseX = e.clientX;
|
||||
mouseY = e.clientY;
|
||||
});
|
||||
|
||||
const interactiveElements = 'a, button, [role="button"], input, textarea, select, .card, .card-sponsors';
|
||||
|
||||
document.addEventListener('mouseover', (e) => {
|
||||
if (e.target.closest(interactiveElements)) {
|
||||
cursor.classList.add('hover');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseout', (e) => {
|
||||
if (e.target.closest(interactiveElements)) {
|
||||
cursor.classList.remove('hover');
|
||||
}
|
||||
});
|
||||
|
||||
function updateCursor() {
|
||||
const dx = mouseX - cursorX;
|
||||
const dy = mouseY - cursorY;
|
||||
|
||||
velocityX += dx * ease;
|
||||
velocityY += dy * ease;
|
||||
|
||||
velocityX *= friction;
|
||||
velocityY *= friction;
|
||||
|
||||
cursorX += velocityX;
|
||||
cursorY += velocityY;
|
||||
|
||||
cursor.style.transform = `translate(${cursorX - 4}px, ${cursorY - 4}px)`;
|
||||
|
||||
requestAnimationFrame(updateCursor);
|
||||
}
|
||||
|
||||
updateCursor();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user