14

我有声明宽度和高度的图像,例如:

<img src="foo.jpg" width="1500" height="1800" alt="bar" />

它们位于响应式网格中,因此它们显示在max-width: 100%. 它们是延迟加载的。问题是尽管有,但图像在加载之前height: auto;总是显示为正方形,这会在它们完成加载时创建页面高度的跳跃。

所以上面的图像示例,在我的 960px 宽度网格中,将在 960px x 960px 处显示一个占位符,直到加载完整图像,此时它将是 960px x Y(其中 Y 是正确的高度)。

我的问题是如何让占位符图像模拟实际图像的最终加载尺寸?

4

6 回答 6

4

您可以通过以下解决方案达到预期的效果。

HTML:

<img src="blank.gif" class="lazy" data-src="foo.png" width="1500" height="1800" alt="bar">  
             ▲                ▲  
             ║                ╚═══ The class will be used for the lazy loader below  
             ║  
             ╚═══ Use faulty gif here to hide it from showing before loaded

提示:如果您希望占位符矩形可见并采用一种颜色,请考虑使用 1x1 像素的图像blank.gif。它会加载得非常快,并且会很好地拉伸到您的比例,并用您选择的颜色填充它。

JavaScript:

/* lazyload.js (c) Lorenzo Giuliani
 * MIT License (http://www.opensource.org/licenses/mit-license.html)
 *
 * expects a list of:  
 * `<img src="blank.gif" data-src="my_image.png" width="600" height="400" class="lazy">`
 */

!function(window){
  var $q = function(q, res){
        if (document.querySelectorAll) {
          res = document.querySelectorAll(q);
        } else {
          var d=document
            , a=d.styleSheets[0] || d.createStyleSheet();
          a.addRule(q,'f:b');
          for(var l=d.all,b=0,c=[],f=l.length;b<f;b++)
            l[b].currentStyle.f && c.push(l[b]);

          a.removeRule(0);
          res = c;
        }
        return res;
      }
    , addEventListener = function(evt, fn){
        window.addEventListener
          ? this.addEventListener(evt, fn, false)
          : (window.attachEvent)
            ? this.attachEvent('on' + evt, fn)
            : this['on' + evt] = fn;
      }
    , _has = function(obj, key) {
        return Object.prototype.hasOwnProperty.call(obj, key);
      }
    ;

  function loadImage (el, fn) {
    var img = new Image()
      , src = el.getAttribute('data-src');
    img.onload = function() {
      if (!! el.parent)
        el.parent.replaceChild(img, el)
      else
        el.src = src;

      fn? fn() : null;
    }
    img.src = src;
  }

  function elementInViewport(el) {
    var rect = el.getBoundingClientRect()

    return (
       rect.top    >= 0
    && rect.left   >= 0
    && rect.top <= (window.innerHeight || document.documentElement.clientHeight)
    )
  }

    var images = new Array()
      , query = $q('img.lazy')
      , processScroll = function(){
          for (var i = 0; i < images.length; i++) {
            if (elementInViewport(images[i])) {
              loadImage(images[i], function () {
                images.splice(i, i);
              });
            }
          };
        }
      ;
    // Array.prototype.slice.call is not callable under our lovely IE8 
    for (var i = 0; i < query.length; i++) {
      images.push(query[i]);
    };

    processScroll();
    addEventListener('scroll',processScroll);

}(this);

来源: Lazyload 脚本可以在这里找到。

于 2014-03-24T17:19:27.037 回答
1

以下是唯一 100% 有效的解决方案,而且更简单: https ://css-tricks.com/preventing-content-reflow-from-lazy-loaded-images/

简而言之,您可以使用包含尺寸的 SVG 占位符图像:

<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 2'%3E%3C/svg%3E" data-src="//picsum.photos/900/600" alt="Lazy loading test image" />

这是一个反应示例:

const placeholderSrc = (width, height) => `data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"%3E%3C/svg%3E`

const lazyImage = ({url, width, height, alt}) => {
  return (
    <img
      src={placeholderSrc(width, height)}
      data-src={url}
      alt={alt} />
  )
}
于 2020-03-17T04:52:03.180 回答
0

在这里,我为你做了一个FIDDLE

主要是在它周围生成一个 div 并根据它加载后的高度和宽度设置它。然后您可以将其加载到该容器中,甚至可以产生平滑的效果;)

HTML

<div class="site-wrapper">
    <div class="lazyload" data-src="http://tinyurl.com/py2nunk" data-width="1920" data-height="1200"></div>
</div>

CSS

.site-wrapper {
    width:960px;
}
.lazyload {
    max-width: 100%;
    border: 1px solid #000;
}
.lazyload img {
    max-width: 100%;
}

JAVASCRIPT

$(document).ready(function() {
    $('.lazyload').each(function() {
        var parentwidth = $(this).parent().width();
        var width  = $(this).attr('data-width');    
        var height = $(this).attr('data-height');

        if(parentwidth < width) {
            height = (parentwidth/width*height);
            width = parentwidth;
        }

        $(this).css({ width: width+'px', height: height+'px'});

    });

    // simulating lazyload
    setTimeout(function() {
        $('.lazyload').each(function() {
            img = $('<img>', { 'class': 'lazyloaded' }).css({display: 'none'});
            original = $(this);
            $(img).load( function(){
                original.append(img);
                $(this).fadeIn(200);
            }).attr('src', $(this).attr('data-src'));
        });
    }, 5000);
});

让我知道这是否是您需要的,以便我可以根据您的需要进行更改。

于 2014-03-24T17:17:55.390 回答
0

马上我注意到您使用 px 而不是 % 作为宽度和高度。响应式 HTML 5 DOCType。你应该使用百分比。那里有许多手机和平板电脑访问您的网站。

在标题中使用元标记视口。尝试这样的事情

 <meta name="viewport" content="initial-scale=1, maximum-scale=1">

有关如何为任何设备正确调整网页大小的更多信息,请访问此处https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag

我提醒您使用 CSS 来控制图像的高度和宽度,如果可能的话尽量远离属性。在 CSS 代码中使用 min 和 max 以及宽度和高度扇区作为宽度和高度。你不需要 JavaScript 来解决你的问题

于 2014-03-31T04:17:08.960 回答
0

您能否在 css 中为图像添加所需的最大高度。我认为这会解决你的问题。

于 2014-03-31T12:02:24.213 回答
0

在撰写本文时,没有任何答案可以解释为什么会发生这种情况或如何克服它。我发现了另一个与这个问题相同的问题,它解释了一个有趣的“黑客”来解决这个问题。

于 2014-03-31T17:30:14.783 回答