Адаптивные изображения: установите атрибут размеров из JavaScript - PullRequest
0 голосов
/ 02 мая 2018

Атрибут srcset может быть установлен из JavaScript для реализации отзывчивых ленивых загруженных изображений.

Однако установка атрибута sizes, похоже, не работает. Кодирование sizes в HTML работает должным образом, но когда я пытаюсь установить атрибут sizes из JavaScript (как в коде ниже), это не имеет никакого эффекта: выбранное изображение соответствует ширине области просмотра и не следует 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');
  }
}

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Согласно комментарию @ 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';
  }
}
0 голосов
/ 03 мая 2018

Я проверил ваш образец, и он работает нормально, как и ожидалось для меня.

Что-то не так с кодировкой размеров, вероятно.
Я думаю, что не стоит помещать условие min-width: 0px media, так как оно будет всегда выбрано, а все остальные условия будут игнорироваться.

Отсюда https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images

Браузер игнорирует все после первого условия сопоставления, поэтому будьте осторожны при заказе условий мультимедиа.

...