Самый простой JS для ленивой загрузки только для изображений? (без зависимостей, пожалуйста) - PullRequest
0 голосов
/ 25 июня 2018

В поисках простейшего способа: ленивая загрузка JS для загрузки изображений только на сайте портфолио.

Должна работать в любом браузере, не нужно jquery, а просто чистое js-кодирование.У вас должен быть класс CSS с именем ".image-box", где находятся изображения.

Сайт отзывчивый, но не использует разные исходные файлы изображений для разных адаптивных размеров.

Спасибо за помощь.

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

function init() {
    var imgDefer = document.getElementsByTagName('img');

    for (var i = 0; i < imgDefer.length; i++) {
        if (imgDefer[i].getAttribute('data-src')) {
            imgDefer[i].setAttribute('src', imgDefer[i].getAttribute('data-src'));
        }
    }
}
window.onload = init;

Как я могу использовать это на HTML?Хорошо, загрузите скрипт, а затем?

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Обманщик пересечения обманывает?

window.addEventListener("load", function (event) {
  var images = document.querySelectorAll('#lazy-img');
  //if the browser doesn't support IO
  if (!('IntersectionObserver' in window)) {
    LoadImagesOldWay(images);
  } else {
    createObserver(images);
  }
}, false);

function createObserver(images) {
  var options = {
    //root defaults
    root: null,
    rootMargin: "0px",
    //threshold is how much of the element is intersected before firing callback
    threshold: .01
  };
  //create an observer, add the options and callback function
  //then add each image to the observer.
  var observer = new IntersectionObserver(handleIntersect, options);
  images.forEach(function (image) {
    observer.observe(image);
  });

}
//load the smallest image for old browsers
function LoadImagesOldWay(images) {
  images.forEach(function (image) {
    var url = image.getAttribute('data-src');
    image.setAttribute('src', url);
  });
}

function handleIntersect(entries, observer) {
  // Loop through the entries
  entries.forEach(function (entry) {
    //if this entry is intersecting whatsoever
    if (entry.intersectionRatio > 0) {
      var image = entry.target;
      //we get our responsive image set
      var url = image.getAttribute('data-src');
      //and set them as the actual source
      image.setAttribute('src', url);
      //we unobserve (Separate) the image entirely
      observer.unobserve(entry.target);
      console.log('lazy-image loaded!:simpleIO.js line 49 to remove this!');
    }
  });
}

Мне нравится IO, потому что он чрезвычайно устойчив и открыт.Вы можете лениво загрузить что угодно с помощью наблюдателя на пересечении.

Посмотрите пример с отзывчивыми изображениями на моем github

edit-wow пропустил все полученные вами отрицательные голоса.Не уверен, почему кто-то увидел -1 и подумал, что это должно быть еще хуже.Я думал, что это хороший вопрос, просто плохо сформулированный.Не позволяй им добраться до тебя.: D

Простой-Пересечение-Наблюдатель

0 голосов
/ 25 июня 2018

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

Он свободен от зависимостей и использует только обычный DOM API.

Это может быть не идеально, но это должно помочь вам начать.Пожалуйста, дайте мне знать, если вам нужны указатели о том, как реализовать отсутствующий импорт.

import {registerViewportChangeCallback, unregisterViewportChangeCallback,
  elementInView} from './viewportHandler';
import {querySelectorAllCached} from './index';

let lazyCache = {};
let lazyCacheList = [];
let imgElements = null;
let allLoaded = false;

function removeEventListeners (el) {
  el.removeEventListener('load', onLoad);
  el.removeEventListener('error', onError);
}

function onLoad (e) {
  e.target.classList.remove('akm-lazy-loading');
  e.target.classList.add('akm-lazy-loaded');
  removeEventListeners(e.target);
}

function onError (e) {
  e.target.classList.remove('akm-lazy-loading');
  e.target.classList.add('akm-lazy-error');
  removeEventListeners(e.target);
}

function updateImages () {
  if (allLoaded) {
    return;
  }

  if (!imgElements) {
    // Find all images on the page and sort them top to bottom
    // so that we can start preloading the topmost images first
    imgElements = querySelectorAllCached(
      'img[data-src], img[data-srcset]')
      .sort((a, b) => {
        const aTop = a.getBoundingClientRect().top;
        const bTop = b.getBoundingClientRect().top;
        if (aTop < bTop) {
          return -1;
        } else if (bTop > aTop) {
          return 1;
        }
        return 0;
      });
  }

  for (let i = 0; i < imgElements.length; i++) {
    if (lazyCache[i]) {
      continue;
    }

    const el = imgElements[i];
    if (!elementInView(el)) {
      continue;
    }

    loadImage(i);
  }
}

function loadImage (i) {
  const el = imgElements[i];
  lazyCache[i] = true;
  lazyCacheList = Object.keys(lazyCache);

  if (el.src.indexOf('mno_0643') !== -1) {
    // debugger;
  }

  el.addEventListener('load', onLoad);
  el.onLoad = onLoad;
  el.addEventListener('error', onError);
  el.onError = onError;
  el.classList.add('akm-lazy-loading');

  if (el.parentElement.tagName.toLowerCase() === 'picture') {
    for (const src of
      Array.from(el.parentElement.querySelectorAll('source'))) {
      if (src.dataset.srcset) {
        src.srcset = src.dataset.srcset;
        delete src.dataset.srcset;
      }
      if (src.dataset.src) {
        src.src = src.dataset.src;
        delete src.dataset.src;
      }
    }
  }
  if (el.dataset.srcset) {
    el.srcset = el.dataset.srcset;
    delete el.dataset.srcset;
  }
  if (el.dataset.src) {
    el.src = el.dataset.src;
    delete el.dataset.src;
  }

  if (lazyCacheList.length === imgElements.length) {
    onAllLoaded();
  }
}

function onAllLoaded () {
  allLoaded = true;
  unregisterViewportChangeCallback(updateImages);
}

export function initLazyload () {
  registerViewportChangeCallback(updateImages);
}
...