JavaScript - 延迟加载图像回退不会出现在 iOS11 Safari 上
JavaScript - lazy-loading image fallbacks don't appear on iOS11 Safari
我创建了一个脚本,该脚本利用具有 webp 和 jpg 后备元素的元素以及一些延迟加载来提供非常高质量的图像。到目前为止,它在除 iOS11 Safari 之外的每个 'modern' 浏览器中都能完美运行。
我已经为 IntersectionObserver 实现了回退,因为我知道这还没有完全支持,它使用 getClientBoundingRect() 来查找图像在视口中的位置。我检查了 iOS 10、11,然后将其中一台相同的设备升级到 iOS 12,图像开始加载。
<div class="lazy-container">
<picture class="lazy-thumbnail">
<source srcset="{{ asset( '/images/media/placeholders/3.webp' ) }}" type="image/webp">
<source srcset="{{ asset( '/images/media/placeholders/3.jpg' ) }}" type="image/jpeg">
<img class="" src="{{ asset( '/images/media/placeholders/3.jpg' ) }}" />
</picture>
<picture data-lazy>
<source data-srcset="{{ asset( '/images/media/3.webp' ) }}" type="image/webp">
<source data-srcset="{{ asset( '/images/media/3.jpg' ) }}" type="image/jpeg">
<img class="" src="{{ asset( '/images/media/3.jpg' ) }}" />
</picture>
</div>
const lazyObserver = new IntersectionObserver( ( entries, observer ) => {
// Break into function to allow immediate calling
const exchangeImage = ( image, source ) => {
source.forEach( ( s ) => {
s.setAttribute( 'srcset',
s.getAttribute( 'data-srcset' ) );
});
image.previousElementSibling.classList.remove( 'lazy-thumbnail' );
image.previousElementSibling.classList.add( 'ex-lazy-thumbnail' );
image.classList.add( 'ex-lazy' );
image.removeAttribute( 'data-lazy' );
// If the image is in view and src has been swapped out, stop observing the image
lazyObserver.unobserve( image );
};
entries.forEach( ( entry ) => {
const image = entry.target;
const source = image.querySelectorAll( 'source' );
// If the image is either in view or data-lazy='immediate', load the image.
if( entry.target.dataset.lazy === 'immediate' || entry.isIntersecting ){
exchangeImage( image, source );
}
});
});
图片元素应该通过并加载适用于浏览器的第一个图像 srcset,在大多数情况下是 webp,然后选择这些后,JS 应该 运行 当图像在视图中时,换出具有大图像和负载的数据 srcset 的 srcset。这适用于所有浏览器,除了
.lazy-container {
overflow: hidden;
position: relative;
picture {
width: 100%;
position: absolute;
top: 0;
left: 0;
img {
display: block;
width: 100%;
height: auto;
}
}
}
.ex-lazy {
filter: blur(0px);
transition: all 500ms ease-in-out;
}
.lazy-thumbnail {
opacity: 1;
filter: blur(8px);
transition: all 500ms ease-in-out;
z-index: 1;
}
.ex-lazy-thumbnail {
opacity: 0;
filter: blur(0px);
transition: all 500ms ease-in-out;
z-index: 0;
}
[data-lazy]{
width: 100%;
height: auto;
filter: blur(8px);
transition: all 500ms ease-in-out;
}
我用我的方式解决了这个问题。
也看看polyfill可以帮助polyfill
let images = document.querySelectorAll('source, img');
if ('IntersectionObserver' in window) {
// we check if IntersectionObserver is supported by our browsers
let config = {
root: null,
rootMargin: '0px',
threshold: 0.5
};
let observer = new IntersectionObserver(onChange, config);
images.forEach(function (img) { observer.observe(img) });
function onChange(changes, observer) {
changes.forEach(function (change) {
if (change.intersectionRatio > 0) {
// we stop observing and loading pictures
loadImage(change.target);
observer.unobserve(change.target);
}
});
}
} else {
// if IntersectionObserver is not supported, we load all photos
images.forEach(function (image) { loadImage(image) });
}
function loadImage(image) {
image.classList.add('fade-in');
if (image.dataset && image.dataset.src) {
image.src = image.dataset.src;
}
if (image.dataset && image.dataset.srcset) {
image.srcset = image.dataset.srcset;
}
}
// -- How to add polyfil
const modernBrowser = ('IntersectionObserver' in window);
if (!modernBrowser) {
loadScripts([
"./polyfills/intersection-observer.js"
])
}
function loadScripts(array, callback) {
var loader = function (src, handler) {
var script = document.createElement("script");
script.src = src;
script.onload = script.onreadystatechange = function () {
script.onreadystatechange = script.onload = null;
handler();
}
var head = document.getElementsByTagName("head")[0];
(head || document.body).appendChild(script);
};
(function run() {
if (array.length != 0) {
loader(array.shift(), run);
} else {
callback && callback();
}
})();
}
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
<noscript><img src="https://place-hold.it/100x100/15252D/fff"></noscript>
</picture>
我创建了一个脚本,该脚本利用具有 webp 和 jpg 后备元素的元素以及一些延迟加载来提供非常高质量的图像。到目前为止,它在除 iOS11 Safari 之外的每个 'modern' 浏览器中都能完美运行。
我已经为 IntersectionObserver 实现了回退,因为我知道这还没有完全支持,它使用 getClientBoundingRect() 来查找图像在视口中的位置。我检查了 iOS 10、11,然后将其中一台相同的设备升级到 iOS 12,图像开始加载。
<div class="lazy-container">
<picture class="lazy-thumbnail">
<source srcset="{{ asset( '/images/media/placeholders/3.webp' ) }}" type="image/webp">
<source srcset="{{ asset( '/images/media/placeholders/3.jpg' ) }}" type="image/jpeg">
<img class="" src="{{ asset( '/images/media/placeholders/3.jpg' ) }}" />
</picture>
<picture data-lazy>
<source data-srcset="{{ asset( '/images/media/3.webp' ) }}" type="image/webp">
<source data-srcset="{{ asset( '/images/media/3.jpg' ) }}" type="image/jpeg">
<img class="" src="{{ asset( '/images/media/3.jpg' ) }}" />
</picture>
</div>
const lazyObserver = new IntersectionObserver( ( entries, observer ) => {
// Break into function to allow immediate calling
const exchangeImage = ( image, source ) => {
source.forEach( ( s ) => {
s.setAttribute( 'srcset',
s.getAttribute( 'data-srcset' ) );
});
image.previousElementSibling.classList.remove( 'lazy-thumbnail' );
image.previousElementSibling.classList.add( 'ex-lazy-thumbnail' );
image.classList.add( 'ex-lazy' );
image.removeAttribute( 'data-lazy' );
// If the image is in view and src has been swapped out, stop observing the image
lazyObserver.unobserve( image );
};
entries.forEach( ( entry ) => {
const image = entry.target;
const source = image.querySelectorAll( 'source' );
// If the image is either in view or data-lazy='immediate', load the image.
if( entry.target.dataset.lazy === 'immediate' || entry.isIntersecting ){
exchangeImage( image, source );
}
});
});
图片元素应该通过并加载适用于浏览器的第一个图像 srcset,在大多数情况下是 webp,然后选择这些后,JS 应该 运行 当图像在视图中时,换出具有大图像和负载的数据 srcset 的 srcset。这适用于所有浏览器,除了
.lazy-container {
overflow: hidden;
position: relative;
picture {
width: 100%;
position: absolute;
top: 0;
left: 0;
img {
display: block;
width: 100%;
height: auto;
}
}
}
.ex-lazy {
filter: blur(0px);
transition: all 500ms ease-in-out;
}
.lazy-thumbnail {
opacity: 1;
filter: blur(8px);
transition: all 500ms ease-in-out;
z-index: 1;
}
.ex-lazy-thumbnail {
opacity: 0;
filter: blur(0px);
transition: all 500ms ease-in-out;
z-index: 0;
}
[data-lazy]{
width: 100%;
height: auto;
filter: blur(8px);
transition: all 500ms ease-in-out;
}
我用我的方式解决了这个问题。 也看看polyfill可以帮助polyfill
let images = document.querySelectorAll('source, img');
if ('IntersectionObserver' in window) {
// we check if IntersectionObserver is supported by our browsers
let config = {
root: null,
rootMargin: '0px',
threshold: 0.5
};
let observer = new IntersectionObserver(onChange, config);
images.forEach(function (img) { observer.observe(img) });
function onChange(changes, observer) {
changes.forEach(function (change) {
if (change.intersectionRatio > 0) {
// we stop observing and loading pictures
loadImage(change.target);
observer.unobserve(change.target);
}
});
}
} else {
// if IntersectionObserver is not supported, we load all photos
images.forEach(function (image) { loadImage(image) });
}
function loadImage(image) {
image.classList.add('fade-in');
if (image.dataset && image.dataset.src) {
image.src = image.dataset.src;
}
if (image.dataset && image.dataset.srcset) {
image.srcset = image.dataset.srcset;
}
}
// -- How to add polyfil
const modernBrowser = ('IntersectionObserver' in window);
if (!modernBrowser) {
loadScripts([
"./polyfills/intersection-observer.js"
])
}
function loadScripts(array, callback) {
var loader = function (src, handler) {
var script = document.createElement("script");
script.src = src;
script.onload = script.onreadystatechange = function () {
script.onreadystatechange = script.onload = null;
handler();
}
var head = document.getElementsByTagName("head")[0];
(head || document.body).appendChild(script);
};
(function run() {
if (array.length != 0) {
loader(array.shift(), run);
} else {
callback && callback();
}
})();
}
<picture>
<source media="(min-width: 400px)" data-srcset="https://place-hold.it/400x400/15252D/fff">
<source media="(min-width: 200px)" data-srcset="https://place-hold.it/200x200/15252D/fff">
<img data-src="https://place-hold.it/100x100/15252D/fff">
<noscript><img src="https://place-hold.it/100x100/15252D/fff"></noscript>
</picture>