Implement intersection observer for lazy loading of skin images in index.php; adjust CSS for skin grid and image dimensions to enhance layout and user experience.

This commit is contained in:
Bram Suurd
2025-06-29 22:56:49 +02:00
parent e540e1e8e3
commit 048ce5cf5e
2 changed files with 42 additions and 21 deletions

View File

@@ -486,9 +486,26 @@ if (isset($_SESSION['steamid'])) {
// Clear previous skins // Clear previous skins
skinGrid.innerHTML = ''; skinGrid.innerHTML = '';
// Populate skins with lazy loading // Populate skins with intersection observer lazy loading
const skinEntries = Object.entries(skinsData[weaponId]); const skinEntries = Object.entries(skinsData[weaponId]);
// Create intersection observer for lazy loading
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
const imageUrl = img.dataset.src;
if (imageUrl && !img.src) {
img.setAttribute('data-loading', 'true');
img.src = imageUrl;
observer.unobserve(img);
}
}
});
}, {
rootMargin: '100px' // Load images 100px before they're visible
});
skinEntries.forEach(([paintId, skin], index) => { skinEntries.forEach(([paintId, skin], index) => {
const skinItem = document.createElement('div'); const skinItem = document.createElement('div');
skinItem.className = 'skin-item'; skinItem.className = 'skin-item';
@@ -498,28 +515,25 @@ if (isset($_SESSION['steamid'])) {
const img = document.createElement('img'); const img = document.createElement('img');
img.alt = skin.paint_name; img.alt = skin.paint_name;
img.className = 'skin-image'; img.className = 'skin-image';
img.style.minHeight = '300px';
// Add loading placeholder // Only load first 8 images immediately, rest use intersection observer
img.style.background = 'linear-gradient(145deg, #333, #222)'; if (index < 8) {
img.style.minHeight = '180px';
// Lazy load: only load first 12 images immediately, rest on scroll/delay
if (index < 12) {
img.src = skin.image_url; img.src = skin.image_url;
} else { } else {
// Load after a delay or when scrolled into view // Store URL in data attribute for lazy loading
setTimeout(() => { img.dataset.src = skin.image_url;
img.src = skin.image_url; imageObserver.observe(img);
}, index * 50); // Stagger loading
} }
img.onerror = function() { img.onerror = function() {
console.log('Failed to load image:', skin.image_url); console.log('Failed to load image:', skin.image_url);
this.style.background = '#333'; this.style.background = '#444';
this.style.content = '""'; this.removeAttribute('data-loading');
}; };
img.onload = function() { img.onload = function() {
this.style.background = 'transparent'; this.style.background = 'transparent';
this.removeAttribute('data-loading');
console.log('Successfully loaded image:', skin.image_url); console.log('Successfully loaded image:', skin.image_url);
}; };

View File

@@ -403,9 +403,10 @@ body {
} }
.overlay-content { .overlay-content {
width: 1000px; width: 1400px;
height: 700px; height: 800px;
max-height: 85vh; max-height: 95vh;
max-width: 98vw;
} }
.modal-content { .modal-content {
@@ -448,8 +449,8 @@ body {
/* Skin Grid */ /* Skin Grid */
.skin-grid { .skin-grid {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1rem; gap: 1.5rem;
padding: 1.5rem; padding: 1.5rem;
overflow-y: auto; overflow-y: auto;
flex: 1; flex: 1;
@@ -472,14 +473,20 @@ body {
.skin-item .skin-image { .skin-item .skin-image {
width: 100%; width: 100%;
height: 180px; height: 300px;
object-fit: contain; object-fit: contain;
background: linear-gradient(145deg, #333, #222); background: linear-gradient(145deg, #333, #222);
padding: 0.75rem; padding: 0.5rem;
display: block; display: block;
box-sizing: border-box; box-sizing: border-box;
transform: scale(1.2); transform: scale(1.6);
transform-origin: center; transform-origin: center;
transition: opacity 0.3s ease;
}
.skin-item .skin-image[data-loading="true"] {
opacity: 0.6;
background: linear-gradient(145deg, #444, #333);
} }
.skin-name { .skin-name {