2014-05-01 20 views
12

Używam systemu siatki CSS opartego na procentach. Mam siatkę z 4 kolumnami, każda o 25% całkowitej szerokości strony. I wyjściowe mój obraz znaczniki wewnątrz każdej komórki „25%” tak:Leniwe ładowanie z obrazami "responsywnymi" (nieznana wysokość)

<img src="foo.jpg" style="max-width:100%" /> 

jako przeglądarka zmienia rozmiar, zmiana rozmiaru obrazów również wypełnić w 100% każdej komórki 25%. Przeglądarka wybiera wysokość, tak jakbym wstawił "height: auto" (co jest niejawne, gdy pominięto).

Teraz chcę dodać do tego leniwą funkcję ładowania. Problem polega na tym, że przed załadowaniem obrazów ich wysokość na stronie jest nieznana. Przeglądarka musi pobrać obraz &, obserwując współczynnik kształtu i obliczyć jego wysokość. Wcześniej wszystkie obrazy mają wysokość 1 piksela. Ponieważ każdy obraz ma wysokość 1 piksela, wszystkie są uważane za "wewnątrz rzutni" i są natychmiast ładowane.

Obecnie mam dowodu koncepcji gdzie przed wyprowadzania znacznika img, obliczyć współczynnik zdjęcia obrazu na serwerze, i wyjście w atrybucie danych:

<img src="foo.jpg" style="max-width:100%" data-aspect="1.7742" /> 

Następnie, na razie „dokument gotowy”, i pętli każdego obrazu i ustawić stałą«wysokość»wartość w pikselach przed leniwego ładowania:

$('img').each(function() { 
     var img = $(this); 
     var width = img.width(); 
     var ratio = img.data('aspectratio'); 
     var height = width/ratio; 
     $(this).css('height', height+'px'); 
    }); 

To wydaje się działać, w tym sensie, że nie jest już ładuje wszystkie obrazy w tym samym czas, ale ładuje tylko obrazy podczas przewijania.

Wygląda jednak na to, że może powodować nowe problemy, na przykład rozciąganie obrazów w miarę zmiany rozmiaru przeglądarki przez użytkownika. Musiałbym zmienić "wysokość" z powrotem na "auto", gdy wywołanie zwrotne zostanie uruchomione, aby leniwy załadunek został zakończony. To by zajęło się obrazami, które widzi użytkownik - ale obrazy znajdujące się pod spodem nadal będą miały niewłaściwą wartość "wysokości" podczas zmiany rozmiaru przeglądarki. Za każdym razem, gdy zmieni się rozmiar przeglądarki, będę musiał powtórzyć wszystkie obrazy, które były wcześniej pod spodem, zmierzyć ich zaktualizowaną szerokość, odczytać ich proporcje i zaktualizować nową wysokość, a następnie powtórzyć leniwy załadunek, aby obsłużyć wszystko, co jest teraz powyżej zagięcie. Jeśli tego nie zrobię, ładowanie może zostać uruchomione zbyt wcześnie lub zbyt późno, ponieważ obrazy mają niewłaściwą wartość wysokości.

Moje pytanie brzmi, czy istnieją inne sposoby na leniwne ładowanie obrazów o nieznanych wysokościach, poza dokładną metodą, którą tu opisałem, i jakie byłyby tego konsekwencje? Czy jest jakaś wada mojej metody, poza tym, że boli ją programowanie?

+1

Wygląda na to, że się udało. Przeglądarka ma tylko dwa sposoby poznania wymiarów obrazu: do pobrania lub w języku HTML. – Blazemonger

+0

Dzięki za pewność. Wyobrażałem sobie również podejście, w którym leniwy ładuje pierwsze 4 obrazy, a następnie blokuje, aż zostaną ukończone, a następnie ponownie ocenia nowe pozycje pozostałych obrazów. Jedynym problemem jest to, że blokowanie sprawi, że rzeczy będą wolniejsze niż bez leniwego ładowania. –

+1

OK Właśnie dowiedziałem się o sztuczce z podszewką: http://thisisthat.co.uk/notebook/2013-10-07-lazy-loading-responsive-images http://andmag.se/2012/ 10/responsive-images-lazy-load-and-multiserve-images/ –

Odpowiedz

5

Ostatnio miałem podobny problem, łącząc Isotope z Lazy Load w responsywnym układzie. Izotopy określają układ na podstawie szerokości i wysokości obrazów podczas ładowania strony, więc początkowo wszystkie elementy nakładały się, ponieważ Isotope nie obliczał prawidłowego rozmiaru.

Aby upewnić się elementy zastępcze zostały oszczędność przestrzeni, użyłem sztuczki padding-bottom Państwo wymienić: http://thisisthat.co.uk/notebook/2013-10-07-lazy-loading-responsive-images (chociaż to może nie być to, że dokładny postu). Tu jest mój znaczników:

<article class="portfolio-item"> 
     <a class="portfolio-link" href="img/gallery/thumb90.jpg" style="padding-bottom: 66.2%"> 
      <div class="portfolio-image-wrapper"> 
       <img class="portfolio-image" data-original="img/gallery/thumb90.jpg" width="1000" height="662"> 
      </div> 
      <div class="portfolio-text"> 
       <h1 class="portfolio-item-name"> 
        <span href="#" class="icon" data-icon="e"></span> 
        <span class="portfolio-item-tags">Bridals</span> 
       </h1> 
      </div> 
     </a> 
    </article> 

To prawdopodobnie bardziej zaangażowany niż potrzebujesz (ponieważ cały div .portfolio-text jest nakładką, która ma sporo stylu). Prawdziwym kluczem było właśnie wyliczenie dolnego marginesu w oparciu o szerokość i wysokość obrazu (co zrobiłem w szablonie z PHP) i ustawienie tego jako dopełnienia-dołu elementu, który chciałem zapisać w przestrzeni.

+0

W rzeczywistości używamy izotopów również na niektórych stronach! Wystrzeliwuję interwał co 1000ms, podczas gdy wciąż ładuję obrazy, które informują izotop o przerysowaniu. W ten sposób obrazy będą się przesuwać podczas ładowania, zamiast ładowania w jednej dużej kolumnie, a następnie na końcu. Czy robisz to samo i czy możesz opracować, w jaki sposób JS, który "skleja" to wszystko razem, pracuje dla twojego projektu? –

2

Oto bardziej eleganckie rozwiązanie, od komentarzy. To wciąż wymaga pisania po stronie serwera proporcje, ale z obwolutą div:

<div class="lazy"><img src="foo.jpg" style="max-width:100%" data-aspect="0.75" /></div> 

Następnie z JS daję owijki divpadding-bottom:

$('div.lazy').livequery(function() { 
    var c = $(this); 
    var r = c.data('ar'); 
    c.css('padding-bottom', r * 100 + '%'); 
}); 

Daje to div dokładne wymiary, że img ostatecznie zużyje. I wtedy użyć następujących MNIEJ załadować obrazu w tym obszarze, padding zużywa:

div.lazy { 
    max-width:100%; 
    position:relative; 
    img { 
    position:absolute; 
    width:100%; 
    height:100%; 
    } 
} 
5

Nawet sprzątaczka:

  1. wysokość Set i szerokość obrazu na dowolnie dużym numeru (jak 2000px x 1000px)
  2. Zastosuj następującą CSS do każdego z wybranych obrazów (być może za pośrednictwem udostępnionej klasie):
    max-width: 100% i height: auto
  3. Smile wi de :)

kredytowe dla tego podejścia idzie do GitHub użytkownika dryabove, podane w this Github issue

+0

Działa doskonale dla mnie! –

+0

Jeśli chcesz uzyskać obraz zastępczy, np. szare tło z pokrętłem (lub chcesz, aby twój projekt trzymał właściwą strukturę bez niczego widocznego), a obrazek nie został jeszcze załadowany, 'height: auto' nie będzie działać. Brak informacji o obrazie, aby obliczyć prawidłowy stosunek wysokości do szerokości ... –

+0

nie ma szczęścia dla mnie na Chrome 57. Obrazy nieprzewidywalnie zachodzą na siebie pionowo. – evanmcd

Powiązane problemy