当用户将图像滚动到视图中时,如何动态(或延迟)加载图像

我在许多“现代”网站(例如 facebook 和 google 图片搜索)中注意到这一点,当用户向下滚动页面时,页面下方的图片只有在可见视窗区域(在查看源代码时,页面显示了 < em > X 数量的 <img>标记,但是它们不会立即从服务器获取)内才会被载入。这种技术叫什么,它是如何工作的,以及在多少个浏览器中工作。是否有一个 jQuery 插件可以用最少的代码实现这种行为。

剪辑

好处: 有人能解释如果有一个“ onScrolledIntoView”或类似的 HTML 元素事件。如果没有,这些插件是如何工作的?

122367 次浏览

There is a pretty nice infinite scroll plugin here

I've never programmed one myself, but I would imagine this is how it works.

  1. An event is bound to the the window scrolling

    $(window).scroll(myInfinteScrollFunction);
    
  2. The called function checks if scroll top is greater than the window size

    function myInfiniteScrollFunction() {
    if($(window).scrollTop() == $(window).height())
    makeAjaxRequest();
    }
    
  3. An AJAX request is made, specifying which result # to start at, how many to grab, and any other parameters necessary for the data pull.

    $.ajax({
    type: "POST",
    url:  "myAjaxFile.php",
    data: {"resultNum": 30, "numPerPage": 50, "query": "interesting%20icons" },
    success: myInfiniteLoadFunction(msg)
    });
    
  4. The ajax returns some (most-likely JSON formatted) content, and passes them into the loadnig function.

Hope that makes sense.

Some of the answers here are for infinite page. What Salman is asking is lazy loading of images.

Plugin

Demo

EDIT: How do these plugins work?

This is a simplified explanation:

  1. Find window size and find the position of all images and their sizes
  2. If the image is not within the window size, replace it with a placeholder of same size
  3. When user scrolls down, and position of image < scroll + window height, the image is loaded

(Edit: replaced broken links with archived copies)

Dave Artz of AOL gave a great talk on optimization at jQuery Conference Boston last year. AOL uses a tool called Sonar for on-demand loading based on scroll position. Check the code for the particulars of how it compares scrollTop (and others) to the element offset to detect if part or all of the element is visible.

jQuery Sonar

Dave talks about Sonar in these slides. Sonar starts on slide 46, while the overall "load on demand" discussion starts on slide 33.

The Swiss Army knife of image lazy loading is YUI's ImageLoader.

Because there is more to this problem than simply watching the scroll position.

I came up with my own basic method which seems to work fine (so far). There's probably a dozen things some of the popular scripts address that I haven't thought of.

Note - This solution is fast and easy to implement but of course not great for performance. Definitely look into the new Intersection Observer as mentioned by Apoorv and explained by developers.google if performance is an issue.

The JQuery

$(window).scroll(function() {
$.each($('img'), function() {
if ( $(this).attr('data-src') && $(this).offset().top < ($(window).scrollTop() + $(window).height() + 100) ) {
var source = $(this).data('src');
$(this).attr('src', source);
$(this).removeAttr('data-src');
}
})
})

Sample html code

<div>
<img src="" data-src="pathtoyour/image1.jpg">
<img src="" data-src="pathtoyour/image2.jpg">
<img src="" data-src="pathtoyour/image3.jpg">
</div>

Explained

When the page is scrolled each image on the page is checked..

$(this).attr('data-src') - if the image has the attribute data-src

and how far those images are from the bottom of the window..

$(this).offset().top < ($(window).scrollTop() + $(window).height() + 100)

adjust the + 100 to whatever you like (- 100 for example)

var source = $(this).data('src'); - gets the value of data-src= aka the image url

$(this).attr('src', source); - puts that value into the src=

$(this).removeAttr('data-src'); - removes the data-src attribute (so your browser doesn't waste resources messing with the images that have already loaded)

Adding To Existing Code

To convert your html, in an editor just search and replace src=" with src="" data-src="

Lazy loading images by attaching listener to scroll events or by making use of setInterval is highly non-performant as each call to getBoundingClientRect() forces the browser to re-layout the entire page and will introduce considerable jank to your website.

Use Lozad.js (just 569 bytes with no dependencies), which uses IntersectionObserver to lazy load images performantly.

Im using jQuery Lazy. It took me about 10 minutes to test out and an hour or two to add to most of the image links on one of my websites (CollegeCarePackages.com). I have NO (none/zero) relationship of any kind to the dev, but it saved me a lot of time and basically helped improve our bounce rate for mobile users and I appreciate it.

This Link work for me demo

1.Load the jQuery loadScroll plugin after jQuery library, but before the closing body tag.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script><script src="jQuery.loadScroll.js"></script>

2.Add the images into your webpage using Html5 data-src attribute. You can also insert placeholders using the regular img's src attribute.

<img data-src="1.jpg" src="Placeholder.jpg" alt="Image Alt"><img data-src="2.jpg" src="Placeholder.jpg" alt="Image Alt"><img data-src="3.jpg" src="Placeholder.jpg" alt="Image Alt">

3.Call the plugin on the img tags and specify the duration of the fadeIn effect as your images are come into view

$('img').loadScroll(500); // in ms

You can now use loading="lazy" on the images as well as iframes so that it defers the loading until the user scrolls to that element.

<img src="http://placeimg.com/640/360/any" loading="lazy" />

As quoted in MDN:

Loading attribute The loading attribute on an element (or the loading attribute on an ) can be used to instruct the browser to defer loading of images/iframes that are off-screen until the user scrolls near them.

Can I use?

You can use on all modern browsers for the images, but iframes are experimental as of now.

@import url('https://fonts.googleapis.com/css2?family=Oswald&display=swap');


.scroll-down {
height: 100vh;
background: #037ef3;
display: grid;
place-items: center;
color: #fff;
font-family: "Oswald";
font-size: 2em;
}


.image {
padding: 2em;
display: grid;
place-items: center;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
}
<div class="scroll-down">
Let me take this space so that you can scroll down
</div>
<div class="image">
<img src="http://placeimg.com/640/360/any" loading="lazy" /> <!-- The only important part -->
</div>

Tip:

As you can see in the demo, it creates layout shift which will create a bad UX while scrolling. So try to use placeholders. Something similar like this: NextJS Placeholder