代码之家  ›  专栏  ›  技术社区  ›  Colin

如何使图像仅在视口中时加载?

  •  11
  • Colin  · 技术社区  · 16 年前

    这些天我看到了很多网站,主要是教程网站,它们有很多图片,一旦进入查看端口,它们只会将图片加载到页面的下游?

    3 回复  |  直到 6 年前
        2
  •  29
  •   Ciro Santilli OurBigBook.com    6 年前

    <img loading="lazy" 它没有任何Javascript吗

    您可以在下面的代码片段中看到这一点。

    要查看加载实际上是惰性的,请打开 Chrome DevTools 在“网络”选项卡中。

    然后,当您向下滚动代码段时,您将看到图像只有在看到它们时才会加载。

    我还添加了一个可选的JavaScript按钮,显示您可以进行更改 lazy eager 然后,图像将立即开始加载。

    document.getElementById('load-now').addEventListener('click', function(){
      for (const img of document.getElementsByTagName('img')) {
        img.loading = 'eager';
      }
    });
    .separator {
        height: 1000px;
        width: 100px;
        border: 5px solid red;
    }
    img {
        height: 340px;
        border: 5px solid black;
    }
      #load-now {
      border: 5px solid black;
      }
    <div id="load-now">Click me to load all images now!</div>
    <div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
    <div class="separator"></div>
    <div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
    <div class="separator"></div>
    <div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
    <div class="separator"></div>
    <div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
    <div class="separator"></div>
    <div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
    <div class="separator"></div>
    <div><img loading="lazy" height="340" src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>

    src= Lazy image loading with semantic markup

    IntersectionObserver

    这是一个JavaScript方法,以前可以使用 img loading="lazy" 已实施。

    这基本上是在以下方面使用的技术: https://appelsiini.net/projects/lazyload/ 在以下会议上提到: https://stackoverflow.com/a/2322042/895245

    Web API现在已经发展得如此之快,从零开始编写代码并不困难!

    var observer = new IntersectionObserver(
        (entries, observer) => {
            entries.forEach(entry => {
                if (entry.intersectionRatio > 0.0) {
                    img = entry.target;
                    if (!img.hasAttribute('src')) {
                        alert('will load the image!!!');
                        img.setAttribute('src', img.dataset.src);
                    }
                }
            });
        },
        {}
    )
    for (let img of document.getElementsByTagName('img')) {
        observer.observe(img);
    }
    .separator {
        height: 1000px;
        width: 100px;
        border: 5px solid red;
    }
    img {
        height: 340px;
        border: 5px solid black;
    }
    <div><img data-src="https://upload.wikimedia.org/wikipedia/commons/5/56/Donald_Trump_official_portrait.jpg"></div>
    <div class="separator"></div>
    <div><img data-src="https://upload.wikimedia.org/wikipedia/commons/8/8d/President_Barack_Obama.jpg"></div>
    <div class="separator"></div>
    <div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d4/George-W-Bush.jpeg"></div>
    <div class="separator"></div>
    <div><img data-src="https://upload.wikimedia.org/wikipedia/commons/d/d3/Bill_Clinton.jpg"></div>
    <div class="separator"></div>
    <div><img data-src="https://upload.wikimedia.org/wikipedia/commons/9/90/George_H._W._Bush%2C_President_of_the_United_States%2C_1989_official_portrait_%28cropped%29.jpg"></div>
    <div class="separator"></div>
    <div><img data-src="https://upload.wikimedia.org/wikipedia/commons/1/16/Official_Portrait_of_President_Reagan_1981.jpg"></div>

    全页演示: https://cirosantilli.com/web-cheat/js-image-load-viewport.html

    https://github.com/cirosantilli/cirosantilli.github.io/blob/1f637bf4791b115777300f48f427f0a6bb409fc1/web-cheat/js-image-load-viewport.html

    在铬76中测试。

    这是之后丢失的最后一个用例 loading="lazy" 对我来说:一种急切下载的方法,但将下载顺序更改为先在viewport上下载,然后在下面下载,然后在上面下载: Change loading order of images already on page

    也许我们可以用它做点什么 querySelectorAll() 解决 jQuery find next/prev elements of a certain class but not necessarily siblings 然后移除 loading=lazy

    最后一个问题是如何获取第一个可见元素:

    我还没有看到一个很好的解决方案。

    延迟加载视频

    不知道为什么,但Chromium 81和Firefox 77.0.1都不能延迟加载视频,现在可以确定为什么他们只是为了 img ?

    iframe 然而,这正是YouTube Embeddes使用的,而Firefox 77.0.1没有: lazy load iframe (delay src http call) with jquery

        3
  •  19
  •   Lenar Hoyt    8 年前

        <script type="text/javascript">
            refresh_handler = function(e) {
            var elements = document.querySelectorAll("*[realsrc]");
            for (var i = 0; i < elements.length; i++) {
                    var boundingClientRect = elements[i].getBoundingClientRect();
                    if (elements[i].hasAttribute("realsrc") && boundingClientRect.top < window.innerHeight) {
                        elements[i].setAttribute("src", elements[i].getAttribute("realsrc"));
                        elements[i].removeAttribute("realsrc");
                    }
                }
            };
    
            window.addEventListener('scroll', refresh_handler);
            window.addEventListener('load', refresh_handler);
            window.addEventListener('resize', refresh_handler);
        </script>
    
        4
  •  11
  •   Cerin    16 年前

    用占位符替换图像(例如,只需将“src”属性更改为其他属性,这样图像就不会加载,但url仍然可以访问),然后将窗口滚动事件绑定到一个函数,该函数将查找当前滚动位置的所有图像,并将图像src替换为真正的img标记。

    这是密码。这是未经测试的,但这应该是基本想法:

    <img src="" realsrc="/myimage.png" />
    
    $(document).ready(function(){
    
      $(window).scroll(function(){
        $('img[realsrc]').each(function(i){
          var t = $(this);
          if(t.position().top > ($(window).scrollTop()+$(window).height()){
            t.attr('src', t.attr('realsrc')); // trigger the image load
            t.removeAttr('realsrc'); // so we only process this image once
          }
        });
      })
    
    });