3 minutes to get lazy loading images

What are image lazy loading

Pictures of lazy loading the page is opened, not all pages all-time display of pictures, but only show pictures in the current viewport, in general use in the mobile terminal (PC terminal mainly the front page or back-end pagination).

Why do we need lazy loading

For a page loading speed is one of the most influential factor is the picture of resources, if a page image too much (such as a treasure, an East etc.), the entire page image size can reach hundreds of megabytes, even in the hundreds of megabytes of broadband, all downloads then also need time on ten seconds, which for users is a huge test of patience, not to mention poor network place.

Therefore, lazy loading is to be done for the picture page does not appear in the visible region is not loaded before handling, loading only first greeted pictures, due to the small picture viewable area of ​​the display, it will load faster greatly enhance the user experience will be better.

Also, the user may only look at a two withdrew, did not see the rest of the picture will not need to load up. This is equivalent to saving bandwidth resources.

Lazy loading implementation principle

Because the browser will automatically send a request to the src attribute of the img tag page and download pictures. Therefore, html5 custom attributes data-xxxto the temporary value of src, then when you want to display, then data-xxxthe value of re-assignment to the img src attribute.

Implementation code

Here we simulate two situations:

I.

1, the front end has to get all the pictures, and now these images need to be displayed in a form of lazy loading.

Examples are as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>懒加载Demo1</title>
    <style>
        .box {
            width: 600px;
            margin: 0 auto;
        }

        img {
            width: 100%;
        }
    </style>
</head>
<body>
    <div class="box">
        <img src="./images/1.jpg" alt="">
        <img src="./images/2.jpg" alt="">
        <img src="./images/3.jpg" alt="">
        <img src="./images/4.jpg" alt="">
        <img src="./images/5.jpg" alt="">
        <img src="./images/6.jpg" alt="">
        <img src="./images/7.jpg" alt="">
        <img src="./images/8.jpg" alt="">
        <img src="./images/9.jpg" alt="">
        <img src="./images/10.jpg" alt="">
    </div>
</body>
</html>

As can be seen, 10 images are loaded all at once finished.

The following transformation into a lazy loading:

The picture on the first page of the src attribute is set to an empty string, and true path of the pictures is set in data-src attribute.

When the page scrolling when you need to listen for scrollthe event, the callback scroll events, judge our lazy loading of images to determine whether there is within the viewport, if present within the viewport, then data-srcassigned to src.

How to determine whether an element within the viewport it?

By getBoundingClientRect()acquiring the location and size of the element method. This method returns a named ClientRect的DOMRectobject that contains a top, right, botton, left, width height values.

随着滚动条的向下滚动,bound.top会越来越小,也就是图片到可视区域顶部的距离越来越小,当bound.top <= clientHeight时,图片的上沿应该是位于可视区域下沿的位置的临界点,再滚动一点点,图片就会进入可视区域。

function isInSight(el) {
  const bound = el.getBoundingClientRect();
  const clientHeight = window.innerHeight;
  //如果只考虑向下滚动加载
  //const clientWidth = window.innerWeight;
  return bound.top <= clientHeight + 100; // 这里有个+100是为了提前加载。
}

源代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>懒加载Demo1</title>
    <style>
        .box {
            width: 600px;
            margin: 0 auto;
        }

        img {
            width: 100%;
            height: 600px;
        }
    </style>
</head>
<body>
    <div class="box">
        <img src="" alt="" data-src="./images/1.jpg">
        <img src="" alt="" data-src="./images/2.jpg">
        <img src="" alt="" data-src="./images/3.jpg">
        <img src="" alt="" data-src="./images/4.jpg">
        <img src="" alt="" data-src="./images/5.jpg">
        <img src="" alt="" data-src="./images/6.jpg">
        <img src="" alt="" data-src="./images/7.jpg">
        <img src="" alt="" data-src="./images/8.jpg">
        <img src="" alt="" data-src="./images/9.jpg">
        <img src="" alt="" data-src="./images/10.jpg">
    </div>
</body>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
    $(function () {
        // 第一次需要先加载一次
        lazyLoad();

        $(window).scroll(lazyLoad);

        function isInSight(el) {
            const bound = el.getBoundingClientRect();
            const clientHeight = $(window).height(); // 可视区高度
            return bound.top <= clientHeight + 100; // 这里有个+100是为了提前加载。
        }
        function lazyLoad() {
            $.each($('.box img'), (index,item)=>{
                if(isInSight(item)) {
                    $(item).attr('src', $(item).attr('data-src'));
                }
            });
        }
    });
</script>
</html>

当向下滑动的时候,从Network面板可以看到,剩下的图片是一个个加载的。

可能有人疑问为什么第一次加载了4张,而不是3张?

因为我在判断是否在可视区内加了100 ,return bound.top <= clientHeight + 100; 可以提前加载一张图片。

注意:一定要设置图片的高度。

提示:src的赋值在js原生和jq是不同的,混用的话不会生效。

用js原生方法:document.getElementById("imageId").src = "xxxx.jpg";
用Jquery方法:$("#imageId").attr("src","xxxx.jpg");

而下面的两种都不会生效:
$("#imageId").src = "xxxx.jpg";
document.getElementById("imageId").attr("src","xxxx.jpg");

切记!


情况二

2、前端从后端获取图片进行展示,后端进行分页。

思路:当页面滚动的时候需要去监听scroll事件,在scroll事件的回调中,判断滚动条是否滚动到最底部,如果是,则将将图片的 src 属性设置为data-src的值。

判断是否滚动到最底部的方法:滚动条到顶部距离 + 可视页面高度 >= 当前页面高度

var seeHeight = document.documentElement.clientHeight; // 可视页面高度 
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条到顶部距离
var bodyHeight = document.body.offsetHeight // 当前页面高度

然后判断: scrollTop  + seeHeight  >= bodyHeight 

当滚动条到达底部的时候,获取后端分页的数据。

这里使用一个模拟接口来获取数据: https://www.apiopen.top/meituApi?page=1

page为页码数,一次返回20条数据。当page=0时,会随机返回一页数据,page>=1时会返回相应页码的数据。

源代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>懒加载Demo1</title>
    <style>
        .box {
            width: 600px;
            margin: 0 auto;
        }

        img {
            width: 100%;
            height: 600px;
        }
    </style>
</head>
<body>
    <div class="box"></div>
</body>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script>
    $(function () {

        let pageNum = 2; // 因为第一页没有图片,我从第二页开始的

        getImage(pageNum);

        $(window).scroll(lazyLoad);

        function getImage(pageNum) {
            $.ajax({
                url:'https://www.apiopen.top/meituApi?page='+pageNum,
                type: 'GET',
                success(res) {
                    // 遍历图片,将图片加入div中
                    if(res.code === 200 && res.data) {
                        res.data.forEach((item,index)=>{
                            $('.box').append(`<img src="${item.url}">`);
                        });
                    }
                },
            });
        }

        function lazyLoad() {
            let seeHeight = document.documentElement.clientHeight;
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            let bodyHeight = document.body.offsetHeight;

            if((Math.ceil(seeHeight + scrollTop) >= bodyHeight)) {  // 向上取整的原因是可能有小数
                getImage(++pageNum);
            }
        }
    });
</script>
</html>

当滚动到20张图的底部的时候,就会发出ajax请求,请求下一页数据。

至此本文完,有疑问可以在评论区随时交流哈。

Guess you like

Origin www.cnblogs.com/lvonve/p/12098109.html