【问题标题】:How do I only load an image when the user scrolls to it如何仅在用户滚动到图像时才加载图像
【发布时间】:2010-06-29 10:10:46
【问题描述】:

当用户向下滚动页面足够远以实际看到它们时,许多网站似乎只下载图像或生成文档的一部分(例如用于评论)。

这显然可以让您更快地加载页面并为那些不想向下滚动的人节省带宽。

这是如何完成的,最好是使用 jquery?或者换个方式问,我如何检测丢失的图像刚刚滚动到视图中并需要获取?

【问题讨论】:

  • 虽然我能理解开发人员想要这样做的原因,但我确实觉得等待部分页面加载非常烦人。另外,如果您立即滚动到页面底部,因为内容加载页面会跳转,所以请务必将您的元素设置为块,这样内容就不会跳来跳去让我哭泣;)
  • 这个跳跃的东西很容易通过在HTML中设置图片的高度和宽度来解决,例如。这也是最佳实践

标签: jquery performance image scroll lazy-loading


【解决方案1】:

这是我自己的。玩得开心。 (不需要 jQuery!)

已测试: IE 5.5+、FF 2+、Chrome、Opera 9.6+

用法:

  1. 您的延迟加载图像应该在 thumb 属性中包含它们的真实 src

  2. 只需在内联或外部包含 javascript 文件。

  3. 如果您不想在整个页面上使用它,可以这样做:

     LazyImg().destroy(); // stop global fetching
     LazyImg("watch-only-this-div");
    

    注意:当您包含文件时,已经在整个文档中创建了一个全局实例。您需要先停止它并启动您自己的实例。

    1. 为预取设置自定义偏移量(应在折叠下方多远的位置获取图像)

       // watch the whole document
       // prefetch offset: 300px
       LazyImg(document, 300); 
      

代码:

//
//  LAZY Loading Images 
//
//  Handles lazy loading of images in one or more targeted divs, 
//  or in the entire page. It also keeps track of scrolling and 
//  resizing events, and removes itself if the work is done. 
//
//  Licensed under the terms of the MIT license.
//
//  (c) 2010 Balázs Galambosi
//

(function(){

// glocal variables
var window    = this, 
    instances = {},
    winH;

// cross browser event handling
function addEvent( el, type, fn ) {
  if ( window.addEventListener ) {
    el.addEventListener( type, fn, false );
  } else if ( window.attachEvent ) {
    el.attachEvent( "on" + type, fn );
  } else {
    var old = el["on" + type];
    el["on" + type] = function() { old(); fn(); };
  }
}

// cross browser event handling
function removeEvent( el, type, fn ) {
  if ( window.removeEventListener ) {
    el.removeEventListener( type, fn, false );
  } else if ( window.attachEvent ) {
    el.detachEvent( "on" + type, fn );
  }
}

// cross browser window height
function getWindowHeight() {
  if ( window.innerHeight ) {
    winH = window.innerHeight;
  } else if ( document.documentElement.clientHeight ) {
    winH = document.documentElement.clientHeight;
  } else if ( document.body && document.body.clientHeight ) {
    winH = document.body.clientHeight;
  } else {        // fallback:
    winH = 10000; // just load all the images
  }
  return winH;
}

// getBoundingClientRect alternative
function findPos(obj) {
  var top  = 0;
  if (obj && obj.offsetParent) {
    do {
      top += obj.offsetTop || 0;
      top -= obj.scrollTop || 0;
    } while (obj = obj.offsetParent); // 
    return { "top" : top };
  }
}

// top position of an element
var getTopPos = (function() {
  var dummy = document.createElement("div");
  if ( dummy.getBoundingClientRect ) {
    return function( el ) { 
      return el.$$top || el.getBoundingClientRect().top;
    };
  } else {
    return function( el ) { 
      return el.$$top || findPos( el ).top;
    };
  }
})();

// sorts images by their vertical positions
function img_sort( a, b ) {
  return getTopPos( a ) - getTopPos( b );
}

// let's just provide some interface 
// for the outside world
var LazyImg = function( target, offset ) {

  var imgs,    // images array (ordered)
      last,    // last visible image (index)
      id,      // id of the target element
      self;    // this instance

  offset = offset || 200; // for prefetching

  if ( !target ) {
    target = document;
    id = "$document";
  } else if ( typeof target === "string" ) {
    id = target;
    target = document.getElementById( target );
  } else {
    id = target.id || "$undefined";
  }

  // return if this instance already exists
  if ( instances[id] ) {
    return instances[id];
  }

  // or make a new instance
  self = instances[id] = {

    // init & reset
    init: function() {
      imgs = null;
      last = 0;
      addEvent( window, "scroll", self.fetchImages );
      self.fetchImages();
      return this;
    },

    destroy: function() { 
      removeEvent( window, "scroll", self.fetchImages );
      delete instances[id];
    },

    // fetches images, starting at last (index)
    fetchImages: function() {

      var img, temp, len, i;

      // still trying to get the target
      target = target || document.getElementById( id );

      // if it's the first time
      // initialize images array
      if ( !imgs && target ) {

        temp = target.getElementsByTagName( "img" ); 

        if ( temp.length ) {
          imgs = [];
          len  = temp.length;
        } else return;

        // fill the array for sorting
        for ( i = 0; i < len; i++ ) {
          img = temp[i];
          if ( img.nodeType === 1 && img.getAttribute("thumb") ) {

              // store them and cache current
              // positions for faster sorting
              img.$$top = getTopPos( img );
              imgs.push( img );
          }
        }
        imgs.sort( img_sort );
      }

      // loop through the images
      while ( imgs[last] ) {

        img = imgs[last];

        // delete cached position
        if ( img.$$top ) img.$$top = null;

        // check if the img is above the fold
        if ( getTopPos( img ) < winH + offset )  {

          // then change the src 
          img.src = img.getAttribute("thumb");
          last++;
        }
        else return;
      }

      // we've fetched the last image -> finished
      if ( last && last === imgs.length )  {
        self.destroy();
      }
    }  
  };
  return self.init();
};

// initialize
getWindowHeight();
addEvent( window, "load",   LazyImg().fetchImages );
addEvent( window, "resize", getWindowHeight       ); 
LazyImg();

window.LazyImg = LazyImg;

}());

【讨论】:

    【解决方案2】:

    有插件。 Here's one...

    【讨论】:

    • 来自作者:Lazy Load is currently not usable. It does not work with the latest browsers as expected. I have currently no time updating the code myself...
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    相关资源
    最近更新 更多