可以从JavaScript设置srcset
属性以实现响应性延迟加载图像。
但是,设置sizes
属性似乎不起作用。 HTML中的编码sizes
按预期工作,但是当我尝试从JavaScript设置sizes
属性时(如下面的代码中所示),它没有任何效果:所选图像与视口宽度匹配并且不会#39 ; t遵循sizes
提示。
这是设计,还是没有实现?
以下示例代码。
const BASE_URL = 'https://res.cloudinary.com/foobar/f_auto,dpr_auto,q_auto:eco/';
const SIZES = {
0: 'calc(100vw - 60px)',
420: 'calc((100vw - 90px) / 2)',
750: 'calc((100vw - 120px) / 3)',
1200: 'calc((100vw - 150px) / 4)'
}
const WIDTHS = [500, 1000, 1500];
const options = {
rootMargin: '0px 0px 100px 0px',
};
function callback(entries) {
for (const entry of entries) {
if (entry.isIntersecting) {
const lazyImage = entry.target;
const id = lazyImage.dataset.id;
lazyImage.sizes = getSizes();
lazyImage.srcset = getSrcset(id);
io.unobserve(lazyImage);
}
}
}
function getSrcset(id) {
const srcset = [];
for (const width of WIDTHS) {
srcset.push(`${BASE_URL}w_${width}/${id}.jpg ${width}w`);
}
return srcset.join(',');
}
function getSizes() {
const sizes = [];
for (const size in SIZES) {
sizes.push(`(min-width: ${size}px) ${SIZES[size]}`);
}
return sizes.join(',');
}
const images = document.querySelectorAll('img.lazy');
let io;
if (window.IntersectionObserver) {
io = new IntersectionObserver(callback, options);
}
for (const image of images) {
if (window.IntersectionObserver) {
io.observe(image);
} else {
console.log('Intersection Observer not supported');
image.src = BASE_URL + image.getAttribute('data-id' + '.jpg');
}
}
答案 0 :(得分:1)
我运行了你的样本,它正常工作,正如我预期的那样。
大小编码的方式可能有问题。
我认为放置 min-width:0px 媒体条件并不是一个好主意,因为它将始终被选中,所有其他条件将被忽略。
从这里https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images
浏览器在第一个匹配条件后忽略所有内容,因此请注意如何订购媒体条件。
答案 1 :(得分:0)
根据@ amed0zmey的评论,我通过正确获取sizes
代码来解决这个问题。
下面的工作示例。
const BASE_URL = 'https://res.cloudinary.com/foo/f_auto,dpr_auto,q_auto:eco/';
const BREAKPOINTS = [0, 420, 750, 1200];
const DISPLAY_WIDTHS = ['calc(100vw - 60px)', 'calc((100vw - 90px) / 2)',
'calc((100vw - 120px) / 3)', 'calc((100vw - 150px) / 4)'];
const IMAGE_WIDTHS = [500, 1000, 1500];
const options = {
rootMargin: '0px 0px 100px 0px',
};
function callback(entries) {
for (const entry of entries) {
if (entry.isIntersecting) {
const image = entry.target;
const id = image.dataset.id;
image.srcset = getSrcset(id);
io.unobserve(image);
}
}
}
function getSrcset(id) {
const srcset = [];
for (const width of IMAGE_WIDTHS) {
srcset.push(`${BASE_URL}w_${width}/${id}.jpg ${width}w`);
}
return srcset.join(',');
}
function getSizes() {
const sizes = [];
for (let i = 0; i !== BREAKPOINTS.length; ++i) {
let size = `(min-width: ${BREAKPOINTS[i]}px) `;
const nextBreakpoint = BREAKPOINTS[i + 1];
if (nextBreakpoint) {
size += `and (max-width: ${nextBreakpoint}px) `;
}
size += DISPLAY_WIDTHS[i];
sizes.push(size);
}
return sizes.join(',');
}
const images = document.querySelectorAll('img.lazy');
let io;
if (window.IntersectionObserver) {
io = new IntersectionObserver(callback, options);
}
for (const image of images) {
image.sizes = getSizes();
if (window.IntersectionObserver) {
io.observe(image);
} else {
console.log('Intersection Observer not supported');
const id = image.getAttribute('data-id');
image.srcset = getSrcset(id);
image.src = BASE_URL + 'id' + '.jpg';
}
}