Image.onload 回调触发不一致
Image.onload callback is firing inconsistently
我正在创建延迟加载功能,我想在图像成功加载后将图像附加到 DOM 以创建平滑过渡。
我有一个循环遍历具有特定 class 的元素列表的函数,每次滚动时它会逐渐变小。
一旦该列表中的图像被考虑 "visible" 我添加一个 class 并且它不再被函数评估。
我通过数据属性获取SRC,并创建一个新的Image();
我做了一些 css prop 操作,并在添加 onload 函数后添加 src。
这大约有 1/3 的时间有效,大多数图像从不触发 onload 回调并且不会添加到 DOM。
我的脚本如下:
var lazyClass = 'js-lazyload';
function lazyLoader() {
//Sets an elements var that checks how many non-visible elements still exist
// This variable is reset every time lazyLoader() is called
var elements = document.querySelectorAll('.' + lazyClass + ':not(.js-lazyload--visible)');
//If there are no hidden elements left, end the function we don't need to proceed.
if (elements.length === 0) return;
//Loop through the elements array
//Only untoggled elements can be in this array because of the previous check
for(var i = elements.length; i--;) {
var lazyLoadElement = elements[i];
if (
lazyLoadElement.getBoundingClientRect().bottom <= window.innerHeight &&
lazyLoadElement.getBoundingClientRect().bottom > 0 ||
lazyLoadElement.getBoundingClientRect().top <= window.innerHeight &&
lazyLoadElement.getBoundingClientRect().top > 0)
{
//The element was considered visible, let's go!
lazyLoadElement.classList.add('js-lazyload--visible');
var imgData = lazyLoadElement.getAttribute('data-image'),
image = new Image(),
lazyStyle = window.getComputedStyle(lazyLoadElement);
if(lazyStyle.position !== 'relative'){
if(lazyStyle.position !== 'absolute'){
lazyLoadElement.style.position = 'relative';
}
}
image.onload = () => {
lazyLoadElement.classList.add('js-lazyload--loaded');
lazyLoadElement.insertBefore(image, lazyLoadElement.firstChild);
}
image.classList.add('js-lazyload__image')
image.style.position = 'absolute';
image.style.top = 0;
image.style.left = 0;
image.style.width = '100%';
image.style.height = '100%';
image.style.zIndex = '-1';
image.style.objectFit = 'cover';
image.src = imgData;
}
}
}
这里有一个 fiddle 显示了这个问题:
元素红色 - 不可见
元素蓝色 - 可见,但没有图像
元素绿色 - 加载图像可见
https://jsfiddle.net/dalecarslaw/yumv6rft/
否jQuery请
您添加的 onload 回调实际上已正确触发。
这种特殊情况下的问题是使用 var
声明的变量是函数范围的。这意味着当您的 for
循环完成它的迭代时,lazyLoadElement
变量指向所有被 onload
处理程序触发的处理程序的相同元素。
将 lazyloadElement
、imgData
、image
和 lazyStyle
的声明从 var
更改为 let
将使代码像打算。
我正在创建延迟加载功能,我想在图像成功加载后将图像附加到 DOM 以创建平滑过渡。
我有一个循环遍历具有特定 class 的元素列表的函数,每次滚动时它会逐渐变小。
一旦该列表中的图像被考虑 "visible" 我添加一个 class 并且它不再被函数评估。
我通过数据属性获取SRC,并创建一个新的Image();
我做了一些 css prop 操作,并在添加 onload 函数后添加 src。
这大约有 1/3 的时间有效,大多数图像从不触发 onload 回调并且不会添加到 DOM。
我的脚本如下:
var lazyClass = 'js-lazyload';
function lazyLoader() {
//Sets an elements var that checks how many non-visible elements still exist
// This variable is reset every time lazyLoader() is called
var elements = document.querySelectorAll('.' + lazyClass + ':not(.js-lazyload--visible)');
//If there are no hidden elements left, end the function we don't need to proceed.
if (elements.length === 0) return;
//Loop through the elements array
//Only untoggled elements can be in this array because of the previous check
for(var i = elements.length; i--;) {
var lazyLoadElement = elements[i];
if (
lazyLoadElement.getBoundingClientRect().bottom <= window.innerHeight &&
lazyLoadElement.getBoundingClientRect().bottom > 0 ||
lazyLoadElement.getBoundingClientRect().top <= window.innerHeight &&
lazyLoadElement.getBoundingClientRect().top > 0)
{
//The element was considered visible, let's go!
lazyLoadElement.classList.add('js-lazyload--visible');
var imgData = lazyLoadElement.getAttribute('data-image'),
image = new Image(),
lazyStyle = window.getComputedStyle(lazyLoadElement);
if(lazyStyle.position !== 'relative'){
if(lazyStyle.position !== 'absolute'){
lazyLoadElement.style.position = 'relative';
}
}
image.onload = () => {
lazyLoadElement.classList.add('js-lazyload--loaded');
lazyLoadElement.insertBefore(image, lazyLoadElement.firstChild);
}
image.classList.add('js-lazyload__image')
image.style.position = 'absolute';
image.style.top = 0;
image.style.left = 0;
image.style.width = '100%';
image.style.height = '100%';
image.style.zIndex = '-1';
image.style.objectFit = 'cover';
image.src = imgData;
}
}
}
这里有一个 fiddle 显示了这个问题: 元素红色 - 不可见 元素蓝色 - 可见,但没有图像 元素绿色 - 加载图像可见
https://jsfiddle.net/dalecarslaw/yumv6rft/
否jQuery请
您添加的 onload 回调实际上已正确触发。
这种特殊情况下的问题是使用 var
声明的变量是函数范围的。这意味着当您的 for
循环完成它的迭代时,lazyLoadElement
变量指向所有被 onload
处理程序触发的处理程序的相同元素。
将 lazyloadElement
、imgData
、image
和 lazyStyle
的声明从 var
更改为 let
将使代码像打算。