marque section moving faster than expected
This commit is contained in:
parent
8a842d364d
commit
47cb55ab92
@ -71,52 +71,51 @@
|
|||||||
.hero-img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
.hero-img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
||||||
|
|
||||||
|
|
||||||
/* --- Marquee --- */
|
/* --- Marquee --- */
|
||||||
.partners-section {
|
.partners-section {
|
||||||
padding: 2.5rem 0;
|
padding: 2.5rem 0;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
/* Prevents selection while dragging over logos */
|
||||||
}
|
user-select: none;
|
||||||
|
}
|
||||||
.marquee-track {
|
|
||||||
display: flex;
|
|
||||||
gap: 3rem; /* Reduced from 6rem to 3rem for tighter look with fewer items */
|
|
||||||
width: max-content;
|
|
||||||
/* ADJUSTMENT 1: Added padding to ensure track has width even with few items */
|
|
||||||
padding: 0 1rem;
|
|
||||||
/* ADJUSTMENT 2: Increased animation duration from 40s to 80s for smoother speed */
|
|
||||||
animation: marquee 120s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.partner-logo {
|
|
||||||
height: 40px;
|
|
||||||
width: auto;
|
|
||||||
object-fit: contain;
|
|
||||||
filter: grayscale(100%);
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Keep existing text style for names without logos */
|
|
||||||
.partner-item {
|
|
||||||
font-weight: 700;
|
|
||||||
color: #d4d4d8;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
/* ADJUSTMENT 3: Ensure text doesn't break or wrap */
|
|
||||||
white-space: nowrap;
|
|
||||||
/* Flexbox to align text vertically with logos if they appear mixed */
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
/* Give text elements some space if mixed with logos */
|
|
||||||
padding: 0 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes marquee {
|
.marquee-track {
|
||||||
from { transform: translateX(0); }
|
display: flex;
|
||||||
to { transform: translateX(-50%); }
|
gap: 3rem;
|
||||||
}
|
width: max-content;
|
||||||
|
padding: 0 1rem;
|
||||||
|
/* Removed 120s here - will be handled by JS for consistent speed */
|
||||||
|
animation: marquee linear infinite;
|
||||||
|
/* Ensure smooth rendering */
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partner-logo {
|
||||||
|
height: 40px;
|
||||||
|
width: auto;
|
||||||
|
object-fit: contain;
|
||||||
|
filter: grayscale(100%);
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
.partner-logo:hover { opacity: 1; filter: grayscale(0%); }
|
||||||
|
|
||||||
|
.partner-item {
|
||||||
|
font-weight: 700;
|
||||||
|
color: #d4d4d8;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes marquee {
|
||||||
|
from { transform: translateX(0); }
|
||||||
|
to { transform: translateX(-50%); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Cards & Badge */
|
/* Cards & Badge */
|
||||||
|
|||||||
@ -151,32 +151,64 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- Marquee Width Fix ---
|
// --- Marquee Width & Speed Fix ---
|
||||||
// Ensures the partner list is always wide enough to scroll smoothly
|
|
||||||
|
// Helper: Debounce function prevents the code from running too often
|
||||||
|
// (e.g. while scrolling on mobile which triggers resize events)
|
||||||
|
function debounce(func, wait) {
|
||||||
|
let timeout;
|
||||||
|
return function executedFunction(...args) {
|
||||||
|
const later = () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
func(...args);
|
||||||
|
};
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(later, wait);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function adjustMarqueeWidth() {
|
function adjustMarqueeWidth() {
|
||||||
const track = document.getElementById('marquee-track');
|
const track = document.getElementById('marquee-track');
|
||||||
if (!track) return;
|
if (!track) return;
|
||||||
|
|
||||||
// Get the rendered width of the single list
|
// 1. Get the rendered width of the single list of partners
|
||||||
const currentWidth = track.scrollWidth;
|
const currentWidth = track.scrollWidth;
|
||||||
// Target width: We want the track to be at least 200% of screen width
|
|
||||||
// so it has enough room to scroll off-screen before resetting.
|
|
||||||
const targetWidth = window.innerWidth * 2.0;
|
|
||||||
|
|
||||||
// Calculate how many times we need to repeat the list to reach target width
|
// 2. Calculate how many times we need to repeat the list
|
||||||
|
// Target: We want the track to be at least 3x the screen width
|
||||||
|
// so it scrolls smoothly without running out of items before looping.
|
||||||
|
const targetWidth = window.innerWidth * 3;
|
||||||
|
|
||||||
const repeats = Math.max(2, Math.ceil(targetWidth / currentWidth));
|
const repeats = Math.max(2, Math.ceil(targetWidth / currentWidth));
|
||||||
|
|
||||||
// Get the raw HTML content (the first run of the loop)
|
// 3. Store the original HTML (the first run of the loop)
|
||||||
const originalContent = track.innerHTML;
|
const originalContent = track.innerHTML;
|
||||||
|
|
||||||
// Rebuild the track with the repeated content
|
// 4. Rebuild the track with the repeated content
|
||||||
track.innerHTML = '';
|
track.innerHTML = '';
|
||||||
for (let i = 0; i < repeats; i++) {
|
for (let i = 0; i < repeats; i++) {
|
||||||
track.innerHTML += originalContent;
|
track.innerHTML += originalContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- NEW: Calculate Constant Speed ---
|
||||||
|
// The animation moves -50% of the track width.
|
||||||
|
const totalWidth = track.scrollWidth;
|
||||||
|
const distanceToMove = totalWidth / 2;
|
||||||
|
|
||||||
|
// Desired speed in pixels per second (Adjust this number to make it faster/slower)
|
||||||
|
// 50 = Relaxed/Easy reading speed
|
||||||
|
// 100 = Faster
|
||||||
|
const pixelsPerSecond = 50;
|
||||||
|
|
||||||
|
// Duration = Distance / Speed
|
||||||
|
const durationInSeconds = distanceToMove / pixelsPerSecond;
|
||||||
|
|
||||||
|
// Apply the calculated duration
|
||||||
|
track.style.animationDuration = `${durationInSeconds}s`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run on load and resize
|
// Run on load
|
||||||
window.addEventListener('load', adjustMarqueeWidth);
|
window.addEventListener('load', adjustMarqueeWidth);
|
||||||
window.addEventListener('resize', adjustMarqueeWidth);
|
|
||||||
|
// Run on resize (Debounced by 200ms to prevent flickering during scroll)
|
||||||
|
window.addEventListener('resize', debounce(adjustMarqueeWidth, 200));
|
||||||
@ -196,8 +196,15 @@ GEOIP_PATH = BASE_DIR / 'geoip'
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 3. Security Headers (Required for 10k visitors)
|
if not DEBUG:
|
||||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||||
SECURE_SSL_REDIRECT = True
|
SECURE_SSL_REDIRECT = True
|
||||||
SESSION_COOKIE_SECURE = True
|
SESSION_COOKIE_SECURE = True
|
||||||
CSRF_COOKIE_SECURE = True
|
CSRF_COOKIE_SECURE = True
|
||||||
|
else:
|
||||||
|
SECURE_SSL_REDIRECT = False
|
||||||
|
SESSION_COOKIE_SECURE = False
|
||||||
|
CSRF_COOKIE_SECURE = False
|
||||||
|
|
||||||
|
|
||||||
|
CSRF_TRUSTED_ORIGINS = [f"https://{host}" for host in ALLOWED_HOSTS if "ngrok-free.app" in host]
|
||||||
Loading…
x
Reference in New Issue
Block a user