fixed 图片懒加载bug

This commit is contained in:
Vaica committed 2026-02-02 20:38:58 +08:00
1 parent 819b6d6e85
commit f8730d09e6
6 files changed
+216 -85

No files matched your search

+93 -46
View File
@@ -1,96 +1,143 @@
(function() {
// Default configuration
var defaults = {
showTime: 800,
offsetBottom: 0,
offsetTopm: 50,
onLoadBackEnd: function (index, dom) { },
onLoadBackStart: function (index, dom) { }
offsetBottom: 100, // Distance from bottom to start loading
showTime: 1100, // Transition duration (ms)
queueInterval: 200 // Time between showing successive images in queue
};
var observer;
var imageQueue = []; // Queue for images waiting to be shown
var isProcessingQueue = false;
function init(setting) {
// Merge settings
defaults = Object.assign({}, defaults, setting || {});
// Reset observer for PJAX support
// Reset queue
imageQueue = [];
isProcessingQueue = false;
// Disconnect previous observer if exists (for PJAX)
if (observer) {
observer.disconnect();
observer = null;
}
// Check for IntersectionObserver support
if (!window.IntersectionObserver) {
loadAllImages();
return;
}
// Initialize IntersectionObserver
observer = new IntersectionObserver(function(entries, self) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
var img = entry.target;
showImg(img);
// Add to queue instead of loading immediately
addToQueue(img);
// Stop observing this image once it's triggered
self.unobserve(img);
}
});
}, {
rootMargin: defaults.offsetTopm + "px 0px " + defaults.offsetBottom + "px 0px"
rootMargin: "0px 0px " + defaults.offsetBottom + "px 0px",
threshold: 0.01
});
processImages();
observeImages();
}
function processImages() {
if (!observer) {
init(); // Auto-initialize if not ready
function addToQueue(img) {
// Avoid duplicates
if (!imageQueue.includes(img)) {
imageQueue.push(img);
processQueue();
}
// Expanded selector to catch more images
var images = document.querySelectorAll('img.lazyload, img:not(.blog-img):not([data-comp])');
}
function processQueue() {
if (isProcessingQueue) return;
if (imageQueue.length === 0) return;
isProcessingQueue = true;
var img = imageQueue.shift();
loadImage(img, function() {
// After this image starts showing (or fails), process next after delay
setTimeout(function() {
isProcessingQueue = false;
processQueue();
}, defaults.queueInterval);
});
}
function observeImages() {
var images = document.querySelectorAll('img.lazyload, .post-content img:not(.lazy-loaded)');
images.forEach(function(img) {
// Check if already processed or has data-lazy-src
if (img.classList.contains('lazy-loaded')) return;
// Update transition duration based on settings
if (defaults.showTime) {
// We'll set this via inline style or rely on CSS class if it matches default
// But for full control, let's set it
img.style.transitionDuration = (defaults.showTime / 1000) + 's';
}
if (img.getAttribute('data-lazy-src')) {
// Already setup for lazy load, just observe
observer.observe(img);
} else if (img.getAttribute('src')) {
// Convert to lazy load
var src = img.getAttribute('src');
img.setAttribute('data-lazy-src', src);
img.setAttribute('src', 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
observer.observe(img);
}
});
}
function showImg(dom) {
if (dom.getAttribute('data-comp')) return;
dom.setAttribute('data-comp', 'true');
var src = dom.getAttribute('data-lazy-src');
if (!src) return;
function loadImage(img, callback) {
var src = img.getAttribute('data-lazy-src');
if (!src) {
if (callback) callback();
return;
}
// Create a temporary image to preload
var temp = new Image();
temp.onload = function() {
// Prepare for transition
dom.style.opacity = 0;
dom.style.transition = "opacity " + (defaults.showTime / 1000) + "s ease-in-out";
var onComplete = function() {
// Swap source
dom.setAttribute('src', src);
img.src = src;
// Force reflow
void dom.offsetWidth;
// Fade in
dom.style.opacity = 1;
requestAnimationFrame(() => {
requestAnimationFrame(() => {
img.classList.add('lazy-loaded');
img.removeAttribute('data-lazy-src');
// Execute callback immediately after starting animation logic
if (callback) callback();
});
});
};
temp.onload = onComplete;
temp.onerror = function() {
// On error, show anyway
dom.setAttribute('src', src);
dom.style.opacity = 1;
// Fallback
img.src = src;
requestAnimationFrame(() => {
img.classList.add('lazy-loaded');
if (callback) callback();
});
};
temp.src = src;
}
function tryAgain() {
processImages();
function loadAllImages() {
var images = document.querySelectorAll('img.lazyload');
images.forEach(function(img) {
loadImage(img);
});
}
window.lazyLoadInit = init;
window.lazyLoadAgain = tryAgain;
window.lazyLoadRefresh = observeImages;
})();