图片懒加载---方法

方法一

// // 节流
// // setTimeout+闭包
function throttle(fn, interval = 500) {
  let timer = null;
  let firstTime = true;
  return function(...args) {
    if (firstTime) {
      // 第一次加载
      fn.apply(this, args);
      return (firstTime = false);
    }
    if (timer) {
      // 定时器正在执行,跳过
      return;
    }
    timer = setTimeout(() => {
      clearTimeout(timer);
      timer = null;
      fn.apply(this, args);
    }, interval);
  };
}
// // 判断元素是否出现在视口区域
function isElementInViewport(el){
    // Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。
    // 当滚动位置发生了改变,top和left属性值就会随之立即发生变化(因此,它们的值是相对于视口的,而不是绝对的)
    const {top,height,left,width} = el.getBoundingClientRect();
    const w = window.innerWidth || document.documentElement.clientWidth;
    const h = window.innerHeight || document.documentElement.clientHeight;
    return {
        top <= h && (top+height) >=0 && left <= w && (left+width)>=0;
    }
}

// lazyLoad
function LazyLoad(el, options) {
  if (!(this instanceof LazyLoad)) {
    return new LazyLoad(el);
  }
  this.setting = Object.assign(
    {},
    { src: 'data-src', srcset: 'data-srcset', selector: '.lazyload' },
    options
  );
  if (typeof el === 'string') {
      el = document.querySelectorAll(el)
  }
  this.images=Array.from(el)
  this.listener=this.loadImage()
  this.listener()
  this.initEvent()
  LazyLoad.prototype= {
      loadImage(){
          return throttle(function(){
              let startIndex=0;
              while(startIndex<this.images.length){
                  const image = this.images[startIndex]
                  if (isElementInViewport(image)) {
                      const src = image.getAttribute(this.setting.src)
                      const srcset = image.getAttribute(this.setting.srcset)
                      if (image.tagName.toLowerCase()==="img") {
                          if (src) {
                             image.src=src 
                          }
                          if (srcset) {
                              image.srcset=srcset
                          }
                      }else {
                          image.style.backgroundImage=`url(${src})`
                      }
                      this.image.splice(startIndex,1)
                      continue
                  }
                  startIndex++
              }
              if (!this.images.length) {
                  this.destroy()
              }
          }).bind(this)
      },
      initEvent(){
          window.addEventListener('srcoll',this.listener,false)
      },
      destroy(){
          window.addEventListener('scroll',this.listener,false)
          this.images=null;
          this.listener=null;
      }
  }
}

 

方法二

// lazyLoad
function LazyLoad(images, options = {}) {
  if (!(this instanceof LazyLoad)) {
    return new LazyLoad(images, options);
  }
  this.setting = Object.assign(
    {},
    { src: 'data-src', srcset: 'data-srcset', selector: '.lazyload' },
    options
  );
  this.images = images || document.querySelectorAll(this.setting.selector);
  this.observer = null;
  this.init();
}
LazyLoad.prototype.init = function() {
  let self = this;
  let observerConfig = {
    root: null,
    rootMargin: '0px',
    threshold: [0]
  };
  this.observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      const target = entry.target;
      if (entry.intersectionRatio > 0) {
        this.observer.unobserve(target);
        const src = target.getAttribute(this.setting.src);
        const srcset = target.getAttribute(this.setting.srcset);
        if ('img' === target.tagName.toLowerCase()) {
          if (src) {
            target.src = src;
          }
          if (srcset) {
            target.srcset = srcset;
          }
        } else {
          target.getElementsByClassName.backgroundImage = `url(${src})`;
        }
      }
    });
  }, observerConfig);
  this.images.forEach(image => this.observer.observe(image));
};

 

posted @ 2019-03-22 10:34  shengnan_2017  阅读(256)  评论(0编辑  收藏  举报