Масонство и LazyLoad не хотят работать вместе

Я создаю сайт для фотографа. Он должен быть построен с использованием рамки Bootstrap 3, и он хочет иметь кладку с более чем 400 изображениями на одной странице. Для этого работать LazyLoad является обязательным. Я провел несколько дней, пытаясь получить LazyLoad для работы с Desandros Masonry, но без успеха.

Я пробовал все примеры поиска googling, но большинство сообщений/сайтов/форумов просто перенаправляют вас или копируют этот ответ stackoverflow: Сочетание LazyLoad и JQuery Masonry

Я пробовал оба метода, но, к сожалению, у меня ничего нет, кроме седых волос.....: (

Вот упрощенная версия вживую на странице im, работающая над:
http://nr.x10.mx
В этом примере я добавил fade-in на загрузку страницы, но оставил LazyLoad, так как могу заставить его работать.

И здесь у вас есть FIDDLE следующих

var container = document.querySelector('#ms-container');
imagesLoaded( container, function() 
{
   var msnry = new Masonry(container, 
                                     { itemSelector: '.ms-item',
                                       columnWidth: '.ms-item',});
}); 

Вы также можете скачать весь пакет здесь, включая jquery.lazyload.js ЗДЕСЬ

Любая помощь будет высоко оценена


ОБНОВЛЕНИЕ

Здесь вы можете иметь 4 разных примера различных проблем. Я также с радостью заметил, что класс Bootstrap .img-responsive мешает LazyLoad.

1 - Масонство без LazyLoad
2 - Масонство и Lazyload - Масонство ломается, а LazyLoad не влияет
3 - LazyLoad без масонства - LazyLoad не влияет
4 - LazyLoad без масонства и Bootsrap "img-отзывчивый" удален
5 - масонство и LazyLoad с использованием первого метода ответа SO, упомянутого выше
6 - масонство и LazyLoad с использованием второго метода ответа SO, упомянутого выше
Оба последних из них следующая ошибка: [Ошибка] TypeError: 'undefined' не является функцией (оценка "$ container.imagesLoaded" )   глобальный код (5.html, строка 110)

Обновлен zip ЗДЕСЬ

Снова, любое чувство было бы высоко оценено, спасибо

Ответы

Ответ 1

Я сделал вашу работу 5.html, используя файлы javascript fiddle, представленные на SO, который вы опубликовали, ответил Nathan Do. Таким образом, у вас, вероятно, были только плохие версии скриптов.

Сценарии, связанные на этой странице: http://cdn.jsdelivr.net/masonry/2.1.08/jquery.masonry.min.js и http://cdn.jsdelivr.net/jquery.lazyload/1.8.4/jquery.lazyload.js

Здесь ваша оригинальная скрипка, обновленная с помощью этого метода страницы: http://jsfiddle.net/L9RLe/

Ответ 2

В вашем случае, хотя вы создаете кладки и добавляете эффект lazyload, изображения перекрываются.

Вам нужно выполнить следующие шаги:

  • Создайте динамическую структуру HTML для изображений вместе с их соответствующим соотношением высоты и ширины. Примечание: изображения должны обладать необходимыми атрибутами для применения ленивого эффекта загрузки, т.е. class= "ленивый" data-original = "фактический URL-адрес изображения" и src= "dummy imageurl".

  • Примените ленивый эффект загрузки.

  • Затем создайте масонство.

Давайте иметь пример:

Предположим, что у меня есть массив javascript с некоторыми данными, связанными с изображениями, как

var gallery_itemList= [
    {url: "images/example1.jpg", width:"1170", height:"460"},
    {url: "images/example2.jpg", width:"800", height:"320"},
    {url: "images/example3.jpg", width:"1200", height:"870"}];

И ниже прототип для создания динамического html, применяя эффект lazyload и создавая эффект масонства как:

var masonryGallery = {
    gallery :'', // gallery to create
    genarateGallery : function() {
      // generate each item html
      var inHTML="", i;
      for(i=0;i<gallery_itemList.length;i++){
        var iWidth, iHeight, fHeight=0;
        iWidth=parseInt(gallery_itemList[i].width);
        iHeight=parseInt(gallery_itemList[i].height);
        fHeight = Math.round((iHeight*300)/iWidth);

        inHTML+='<div class="item" style="height:'+fHeight+'px">';
        inHTML+='<img class="lazy" src="images/loading.gif" data-original="'+gallery_itemList[i].url+'"/>';
        inHTML+='</div>';   
      }
      //add generated html to gallery
      $(masonryGallery.gallery).append(inHTML);       
    },
    applyLazyload : function(){
      $("img.lazy").lazyload();
    },
    createMasonry : function(){
      // create Masonry
      $(masonryGallery.gallery).masonry({
        columnWidth: 350,
        itemSelector: '.item',
        isFitWidth: true,
        isAnimated: !Modernizr.csstransitions
      }).imagesLoaded(function() {
        $(this).masonry('reload');
      });
    },
    init : function(givenGallery) {
        masonryGallery.gallery = givenGallery; // set gallery 
        masonryGallery.genarateGallery(); // generate gallery html
        masonryGallery.applyLazyload();  // apply lazyload effect
        masonryGallery.createMasonry();  // apply masonry effect
    }
};

/* Gallery Intialisation */
(function(){masonryGallery.init('div#content');})(); 

Ответ 3

Если у вас возникли проблемы с образами, я нашел решение на сайте ниже, хотя это на японском языке.

http://www.webdesignleaves.com/wp/jquery/1340/

Точка использования следующая;

$('img.lazy').load(function(){ ... })

HTML

<div id="works_list">
<div class="work_item">
    <img class="lazy" src="images/dummy.gif" data-original="images/works/thumb/001.jpg" alt="">
    <p>title 1</p>  
</div><!-- end of .work_item-->
<div class="work_item">
    <img class="lazy" src="images/dummy.gif" data-original="images/works/thumb/002.jpg" alt="">
    <p>title 2</p>  
</div><!-- end of .work_item-->
     ....
</div><!-- end of #works_list -->    

JQuery

$("img.lazy").lazyload({
    effect: 'fadeIn',
    effectspeed: 1000,
    threshold: 200
});

$('img.lazy').load(function() {
    masonry_update();
});

function masonry_update() {     
    var $works_list = $('#works_list');
    $works_list.imagesLoaded(function(){
        $works_list.masonry({
            itemSelector: '.work_item', 
            isFitWidth: true, 
            columnWidth: 160
        });
    });
 }

Ответ 4

Просто хочу внести свой вклад в решение этой сложной проблемы.

В основном вам нужно называть функцию кладки layout() каждый раз, когда изображение lazyloaded, потому что, когда вы знаете, каковы будут измерения. Поэтому вы настраиваете функцию lazyload load() для вызова masonry.layout(). Это может вызвать новую проблему, поскольку при начальной загрузке страницы все ваши изображения будут иметь нулевую или почти нулевую высоту (в зависимости от вашего css) и, таким образом, складываются вверху окна просмотра. Когда вы инициализируете lazyload, он увидит все эти изображения в окне просмотра и попытается загрузить их все сразу. Это заставляет вас загружать тонны изображений, а еще хуже - называет кладки десятками или сотнями раз. Не очень быстро.

Мое решение состоит в том, чтобы заставить минимальную высоту на разгруженные изображения до тех пор, пока они не будут разгружены. Это ограничивает количество изображений, которые будут найдены в окне просмотра, изначально, ограничивая количество вызовов лазы и каменной кладки на разумную сумму.

Как только изображение загружено, вы удаляете класс .unloaded, чтобы деконстрировать высоту и позволить ей соответствовать высоте изображения.

HTML

<div id="masonry-container">
    <div class="masonry-item unloaded"><img class="lazy" data-original="image.jpg"></div>
    <!-- Repeat as needed -->
</div>

CSS

.masonry-item {
    width: 33.3%; // I'm doing a 3-column masonry layout
}

.unloaded {
    min-height: 200px;
    // set a minimum default height for image containers
    // this prevents too many images from appearing in the viewport
    // thus causing lazy load to load too many images at once
    // we will use the lazyload .load() callback to remove this fixed 
}

JS

$( document ).ready(function() {    
    // Initialize Masonry
    var container = document.querySelector('#masonry-container');
    var msnry = new Masonry( container, { transitionDuration: 0 } );
    msnry.layout(); // run masonry for first time

    function doMasonry() { msnry.layout(); } // gives us a function handler to call later with window.setTimeout()

    // Initialize lazyload
    $("img.lazy").lazyload({
        effect : "fadeIn", // optional
        load : function() {
            $(this).parent().removeClass("unloaded"); // select the div containing the image and remove the "unloaded" class, thus deconstricting the min-height
            window.setTimeout(doMasonry,100); // trigger masonry again with a 100 ms delay, if we do it too soon, the image may not have loaded, and masonry will layout with the wrong image dimensions (this might be a bit of a hacky way to do it)
        }
    });
});