Wstępne ładowanie obrazów. Utwórz plik z płótna

Wprowadza nowy, niesamowity interfejs API. Jeśli połączysz to API z elementem, możesz uzyskać supernowoczesny moduł ładujący obrazy. W tym artykule dowiesz się, jak to zrobić. Wszystkie te wskazówki działają dobrze w przeglądarce Firefox 4. Niektóre z nich również omówimy alternatywne sposoby aby upewnić się, że działają w przeglądarkach Webkit. Większość z tych interfejsów API nie działa w IE, ale jest to dość łatwy sposób korzystania z nich i może być używany jako rozwiązanie awaryjne.

Byłoby miło, gdyby ktoś napisał w komentarzach, jak obecnie wykorzystuje tę czy inną technologię w swoich projektach.

Pobierz obraz

Aby przesłać plik na serwer, będziesz potrzebować pliku . Ale powinieneś także pozwolić użytkownikowi na przeciąganie i upuszczanie obrazów z pulpitu bezpośrednio na stronę internetową Twojej witryny.

Wielokrotny wybór plików do przesłania

Aby umożliwić użytkownikowi wybranie wielu plików jednocześnie, wstaw atrybut multiple do elementu file

Wstępne przetwarzanie plików

Korzystanie z interfejsu API plików

(Szczegóły dotyczące pracy z interfejsem File API można znaleźć w artykule)

Po wybraniu plików w elemencie pliku za pomocą narzędzia datepicker lub metodą przeciągnij i upuść masz gotową do użycia listę plików.

//from type="file" var filesToUpload = input.files; //lub przy użyciu funkcji „przeciągnij i upuść” onDrop(e) ( filesToUpload = e.dataTransfer.files; )

Upewnij się, że te pliki są obrazami:

If (!file.type.match(/image.*/)) ( // ten plik nie jest obrazem );

Pokaż miniaturę/miniaturę

Istnieją dwie opcje. Możesz użyć FileReadera (z API plików) lub użyć nowa metoda utwórzObiektURL().

utwórz adres URL obiektu()

Var img = document.createElement("img"); img.src = window.URL.createObjectURL(plik);

Czytnik plików

Var img = document.createElement("img"); var czytnik = nowy FileReader(); reader.onload = funkcja(e) (img.src = e.target.result) reader.readAsDataURL(plik);

Korzystanie z płótna

Możesz rysować plik na elemencie w celu jego późniejszej obróbki

Var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0);

Zmiana rozmiaru obrazu

Ludzie są przyzwyczajeni do pobierania zdjęć bezpośrednio z aparatu. W wyniku tego powstają pliki o wysokiej rozdzielczości i niezwykle ciężkie (kilka megabajtów). W zależności od zastosowania możesz zmieniać rozmiar takich obrazów. Sztuka polega na tym, aby po prostu mieć małe płótno (na przykład 800 × 600) i narysować na nim obraz. Oczywiście będziesz musiał zmienić rozmiar płótna, aby zachować proporcje obrazu.

Var MAX_WIDTH = 800; zmienna MAX_HEIGHT = 600; var szerokość = img.width; var wysokość = img.height; if (szerokość > wysokość) ( if (szerokość > MAX_WIDTH) ( wysokość *= MAX_WIDTH / szerokość; szerokość = MAX_WIDTH; ) ) else ( if (wysokość > MAX_HEIGHT) ( szerokość *= MAX_HEIGHT / wysokość; wysokość = MAX_HEIGHT; ) ) canvas .width = szerokość; canvas.height = wysokość; var ctx = canvas.getContext("2d"); ctx.drawImage(img, 0, 0, szerokość, wysokość);

Edycja obrazu

Masz teraz obraz na płótnie. Teraz Twoje możliwości są nieograniczone. Powiedzmy, że chcesz zastosować filtr sepii:

Var imgData = ctx.createImageData(szerokość, wysokość); var dane = imgData.data; var piksele = ctx.getImageData(0, 0, szerokość, wysokość); for (var i = 0, ii = piksele.data.długość; tj< ii; i += 4) { var r = pixels.data; var g =pixels.data; var b = this.pixels.data; data = (r * .393) + (g *.769) + (b * .189); data = (r * .349) + (g *.686) + (b * .168) data = (r * .272) + (g *.534) + (b * .131) data = 255; } ctx.putImageData(imgData, 0, 0);

Załaduj z XMLHttpRequest

Po przesłaniu obrazów do klienta możesz w końcu wysłać je na serwer.

Jak wysłać płótno

Ponownie masz dwie opcje. Możesz przekonwertować canvas na bardzo długi adres URL lub (w przeglądarce Firefox) utworzyć plik z canvas.

canvas.toDataURL()

Var dataurl = canvas.toDataURL("image/png");

Utwórz plik z płótna

Plik Var = canvas.mozGetAsFile("foo.png");

Niepodzielne pobieranie

Pozwól użytkownikowi pobrać tylko jeden plik lub wszystkie pliki jednocześnie.

Pokaż postęp pobierania

Użyj zdarzenia loading, aby utworzyć wskaźnik:

Xhr.upload.addEventListener("postęp", funkcja(e) ( if (e.lengthComputable) ( var percent = Math.round((e.loaded * 100) / e.total); // zrób coś ), false) ;

Użyj FormData

Prawdopodobnie nie chcesz po prostu przesyłać pliku (co można łatwo zrobić za pomocą: xhr.send(file)), ale także dodać informacje osób trzecich(na przykład klucz i tytuł).

W takim przypadku powinieneś utworzyć żądanie wieloczęściowe/dane formularza przy użyciu obiektu FormData

Var fd = nowe dane formularza(); fd.append("imię", "paweł"); fd.append("obraz", canvas.mozGetAsFile("foo.png")); fd.append("klucz", "××××××××××××”); var xhr = nowy XMLHttpRequest(); xhr.open("POST", "http://your.api.com/upload.json"); xhr.send(fd);


Otwórz interfejs API swojej witryny

Być może chcesz, aby inne witryny korzystały z Twojej witryny jako usługi.\

Aby zagrać w grę, musisz wcześniej załadować około 12 obrazów, a obrazy te mogą się różnić w zależności od przypadku. Czyli teraz muszę załadować jakieś 12 obrazów (SVG), a jutro będę potrzebować kolejnych 12. Dlatego też opcja umieszczenia ich w nie jest odpowiednie, ponieważ w tym przypadku będziesz musiał stale ładować wszystkie obrazy, a potrzebuję ich tylko 12. Dlatego zdecydowano się je załadować za pomocą JavaScriptu przed rozpoczęciem gry. Aby to zrobić, zaimplementowałem małą klasę „AssetsPreloader”, która jak dotąd ma jedną metodę „preload”, która pobiera tablicę obiektów w postaci (src: „link”, id: „id”) i ładuje niezbędne obrazy wg łatwe tworzenie instancja klasy Image() (natywna).

Klasa AssetsPreloader ( static preload(arr) ( arr.map((a) => ( niech img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. aktywa || ).push(img); )); ) )

Wszystkie załadowane obrazy trafiają do właściwość statyczna aktywa tej klasy.

Następnym krokiem w kodzie jest renderowanie pierwszej klatki gry, w której te obrazy są już użyte. I ogólnie problem polega na tym, że renderowanie nie następuje. Dochodzi do wykonania kodu, sprawdziłem to, a po nim kod jest wykonywany, ale same obrazy nie są rysowane. O ile rozumiem, dzieje się tak, ponieważ obrazy nie mają czasu na załadowanie (mimo że są ładowane z dysku). Jeśli jednak poprosisz o narysowanie pierwszej ramki bezpośrednio z konsoli przeglądarki, wszystko będzie działać tak, jak powinno, a ramka zostanie narysowana normalnie.

Cały kod wygląda mniej więcej tak:

Klasa AssetsPreloader ( static preload(arr) ( arr.map((a) => ( niech img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. aktywa || ).push(img); this.done = true; )); ) ) AssetsPreloader.preload([ (src: "images/image.svg", id: "id_of_image"), ... ]); // ... GRA.pole.draw();

Ostatecznie pytanie sprowadza się do tego, jak załadować obrazy (i w ogóle różnego rodzaju pliki) tak poprawnie, jak to możliwe, aby do czasu ich załadowania kod nie był dalej wykonywany. Co więcej, być może w tej chwili na ekranie pojawi się jakiś pasek postępu (to znaczy, że skrypt również nie powinien się całkowicie zawieszać). Pierwszą rzeczą, która przyszła mi do głowy, było dodanie całej reszty kodu do wywołania zwrotnego metody preload(), ale ten pomysł nie powiódł się.

Proszę pomóż. Interesuje mnie nie tylko to, jak, ale także to, co jest najbardziej poprawne (najlepsze praktyki i tak dalej).

P.S. Plik skryptu jest podłączony do strony za pomocą odroczenie atrybutu. Podczas korzystania na przykład z async renderowanie albo się odbywa, albo nie (nie mogę powiedzieć, od czego to zależy). Nie chcę jednak dodawać do samego kodu procedur obsługi sprawdzających ładowanie strony, gotowość DOM lub coś podobnego.

Nota autora: Wygląda na to, że ładowanie obrazu jest albo całkowicie pomijane, albo pozostawione niepotrzebnie dużym wtyczkom. Piękne, gładkie i szybkie ładowanie witryna internetowa jest kluczowym elementem dobrego doświadczenia użytkownika, a także zwykłej uprzejmości wobec projektanta. Kto chciałby, aby jego projekt został zniszczony przez powolne ładowanie obrazów linia po linii za każdym razem, gdy wchodzą na stronę?

Wiele witryn, nad którymi pracuję, zawiera dużą ilość zdjęć, a wszystkie zalety szybkiego Internetu są niweczone koniecznością dostarczania materiałów w ultrawysokiej rozdzielczości. rozdzielczość siatkówki dla coraz większej liczby urządzeń. To idealny moment, aby przejąć stery i zacząć kontrolować ładowanie obrazów. W tym artykule pokażę Ci cztery proste metody, które sprawią, że Twoja witryna będzie wyglądać świetnie i ogromnie poprawi jej wydajność.

Za każdym razem, gdy widzę, że obraz ładuje się powoli, przypominam sobie tę klasyczną scenę z facetem z komiksu.

1. Prześlij każdy obraz osobno (pojedynczy zasób)

Jest to technika, którą możesz zastosować do dowolnego lub wszystkich obrazów w witrynie, aby zapobiec (lub przynajmniej ukryć) tradycyjne ładowanie plików JPG linia po linii. Zaczniemy od zawinięcia każdego obrazu do elementu div za pomocą klasy img_wrapper:

< div class = "img_wrapper" >

< img src = "comicbookguy.jpg" alt = "" / >

< / div >

Ten pakujący dostarczy nam trochę dodatkowa kontrola rozmiar naszych obrazów i ich proporcje, czego nie może zagwarantować prosty tag img. Daje także możliwość zastosowania pokrętła ładującego – jako obrazu tła lub jako osobny element– które można ukryć po zakończeniu ładowania obrazu.

W tym przykładzie ograniczymy nasz obraz do proporcji 4:3 – co jest bardzo ważne w przypadku witryn responsywnych. Zauważ, że ukryliśmy obraz również za pomocą opacity: 0;, co daje nam kontrolę nad tym, jak i kiedy go zobaczymy, gdy nadejdzie czas.

Img_wrapper( pozycja: względna; górna część dopełnienia: 75%; przepełnienie: ukryta; ) .img_wrapper img( pozycja: bezwzględna; góra: 0; szerokość: 100%; krycie: 0; )

img_wrapper(

pozycja: względna;

wyściółka wierzchnia: 75%;

przepełnienie: ukryte;

Img_wrapper img (

pozycja: absolutna;

góra: 0;

szerokość: 100%;

nieprzezroczystość: 0;

Każdy obraz w DOM uruchamia zdarzenie ładowania, gdy wszystkie jego dane zostaną załadowane z serwera, a sam obraz zostanie wyrenderowany przez przeglądarkę. Aby przechwycić i powiązać to zdarzenie, będziemy musieli użyć JavaScript. Zacznę od dodania atrybutu onload do tagu obrazu.

< div >

< img src = "comicbookguy.jpg" alt = "" onload = "imgLoaded(this)" / >

< / div >

Dla tych, którzy dopiero zaczynają korzystać ze skryptu i nie widzieli wcześniej czegoś takiego, nazywa się to wbudowanym atrybutem skryptu i pozwala nam powiązać funkcjonalność JavaScript bezpośrednio ze zdarzeniami uruchamianymi z elementów DOM, podobnie jak dodawanie stylów bezpośrednio do elementów za pomocą wbudowanego atrybutu atrybut stylu. Wierzcie lub nie, ale te atrybuty skryptów wbudowanych stanowiły znaczącą część pisania JavaScript w początkach Internetu i, podobnie jak style wbudowane, są obecnie potępiane przez działaczy zajmujących się czystością kodu i semantyką.

Zatem ci z Was, których zniesmaczył widok wbudowanego JavaScriptu i są gotowi uciec, proszę, zostańcie i uwierzcie mi na słowo, że jest to nadal najbardziej wydajny i niezawodna metoda przechwytywanie zdarzenia ładowania obrazu w DOM. Chociaż jestem zwolennikiem postępu i HTML5, nie mam absolutnie nic przeciwko stosowaniu technik oldschoolowych, o ile są one eleganckie i funkcjonalne.

Alternatywą jest indywidualne powiązanie zdarzenia ładowania z każdym obrazem w gotowym dokumencie. Problem pojawia się jednak, gdy obrazy są ładowane przed uruchomieniem gotowego dokumentu i zanim mamy szansę powiązać funkcjonalność ze zdarzeniem ładowania każdego obrazu. Osobnym problemem jest sytuacja, gdy obrazy z poprzedniej sesji są już w pamięci podręcznej przeglądarki i ładują się natychmiast. Przegapiamy wydarzenie i nasza funkcja nie zostaje wywołana. Atrybut onload nie stwarza takich problemów, ponieważ jest, że tak powiem, „wstępnie powiązany” ze zdarzeniem i dlatego jest przetwarzany, gdy przeglądarka analizuje kod HTML.

Nie mam absolutnie nic przeciwko stosowaniu oldschoolowych technik, byle były eleganckie i funkcjonalne.

Po dodaniu atrybutu onload funkcja imgLoaded() zostanie wywołana po załadowaniu obrazu. Trzeba go umieścić plik JavaScript w nagłówku samej strony (po jQuery, jeśli używasz jej w swojej funkcji, i po innych wtyczkach), aby się skompilowała przed przeanalizowaniem treści i załadowaniem obrazów. Jeśli wstawisz funkcję na dole strony, istnieje duża szansa, że ​​obrazy załadują się przed definicją funkcji.

Używając słowo kluczowe dzięki temu możemy wysłać surowy obiekt obrazu DOM do naszej funkcji JavaScript jako argument:

funkcja imgLoaded(img)( var $img = $(img); $img.parent().addClass("załadowano"); );

funkcja imgLoaded(img) (

var $img = $(img);

$obraz rodzic(). addClass("załadowano");

Lub z prostym JavaScriptem:

funkcja imgLoaded(img)( var imgWrapper = img.parentNode; imgWrapper.className += imgWrapper.className ? "załadowany": "załadowany"; );

funkcja imgLoaded(img) (

var imgWrapper = obraz . węzeł nadrzędny;

imgWrapper. nazwa klasy += imgWrapper . Nazwa klasy? „załadowany”: „załadowany”;

Używając JavaScript, możesz szybko przejść DOM o jeden poziom wyżej i dodać załadowaną klasę do zawierającego ją elementu opakowania. Jestem pewien, że zgodzisz się, że jest to zaskakująco eleganckie rozwiązanie. Wybiórczo stylizując tę ​​klasę, możesz teraz wyświetlić załadowany obraz, ustawiając jego krycie na 1:

Img_wrapper.loaded img( krycie: 1; )

img_wrapper. załadowany obraz (

nieprzezroczystość: 1;

Aby proces przebiegł sprawnie, dodamy do obrazka kilka przejść CSS3 i uzyskamy efekt „zanikania” podczas ładowania naszego obrazu.

Img_wrapper img( pozycja: absolutna; góra: 0; szerokość: 100%; krycie: 0; -webkit-przejście: krycie 150 ms; -moz-przejście: krycie 150 ms; -ms-przejście: krycie 150 ms; przejście: krycie 150 ms; )

Img_wrapper img (

pozycja: absolutna;

góra: 0;

szerokość: 100%;

nieprzezroczystość: 0;

Webkit - przejście: krycie 150ms;

Moz - przejście: krycie 150ms;

Ms - przejście: krycie 150ms;

przejście: nieprzezroczystość 150ms;

Zobacz działający przykład na codepen.io, który zawiera alternatywną wersję wyświetlającą pokrętło ładowania.

Progresywne pliki JPG

Na marginesie tej techniki i w odpowiedzi na niektóre opinie, jakie otrzymałem na temat tego artykułu, zdecydowanie warto wspomnieć o „progresywnych” plikach JPG. To kolejna stara technika sięgająca lat 90. XX wieku, polegająca na przechowywaniu plików JPG jako „progresywnych”, a nie „regularnych”, aby zapobiec ładowaniu linia po linii i zamiast tego renderowaniu obrazu klatka po klatce na tej samej wysokości, na której masa. Główną zaletą tej techniki jest to, że zapobiega przeskakiwaniu przychodzących treści po stronie podczas ładowania obrazów.

To, czy efekty takie jak ładowanie pokręteł i zanikanie są irytujące, jest kwestią osobistego gustu, ale ogólnie rzecz biorąc, sztuczka z zawijaniem div rozwiązuje te problemy przy minimalnej liczbie CSS i JavaScript..

Najlepszą rzeczą w stosowaniu techniki zawijania div jest to, że nie musisz się martwić zmianą wysokości obrazów podczas ich ładowania i nie musisz narażać użytkowników na brzydkie grupowanie pikseli, które moim zdaniem może być tak frustrujące dla użytkownika. tak irytujące jak normalne pobieranie. Poza tym to nic nie kosztuje – proces kilkukrotnego ponownego wyświetlania obrazu tak naprawdę powoduje dodatkowe obciążenie urządzeń o niskim poborze mocy. urządzenia mobilne. To, czy efekty takie jak ładowanie pokręteł i zanikanie są irytujące, jest kwestią osobistego gustu, ale w zasadzie sztuczka z zawijaniem div rozwiązuje te problemy przy minimalnej liczbie CSS i JavaScript i nie ma potrzeby polegania na użytkowniku (w sytuacji CMS) podczas zapisywania JPG W pewien sposób.

2. Przesyłaj zbiorczo wiele obrazów

Powyższa technika jest bardzo dobra indywidualne obrazy, ale co, jeśli mamy wybór obrazów, które chcemy wyświetlić w karuzeli lub pokazie slajdów, lub jeśli użyjemy wtyczki układu, takiej jak Masonry? Częstym błędem podczas korzystania z wtyczek karuzelowych/suwaków jest przetwarzanie ich, gdy dokument jest gotowy, często przed załadowaniem wszystkich ich obrazów. Może to spowodować przeskoczenie pokazu slajdów do pustego obrazu, który jeszcze się nie załadował, szczególnie jeśli mamy do czynienia ze zdjęciami w wysokiej rozdzielczości i dużymi rozmiarami plików.

Aby zapobiec temu zjawisku, musisz przetworzyć preferowaną wtyczkę tylko wtedy, gdy wszystkie niezbędne obrazy zostały już załadowane. Używając odmiany powyższej techniki, ponownie dodamy atrybut onload do wszystkich obrazów w naszym pokazie slajdów:

Uwaga: Poniższy znacznik stanowi jedynie uproszczony przykład znacznika wtyczki pokazu slajdów i należy go dostosować do własnych wymagań.

< div id = "Slideshow" >

< img src = "slide_1.jpg" alt = "" onload = "slideLoaded(this)" / >

< img src = "slide_2.jpg" alt = "" onload = "slideLoaded(this)" / >

< img src = "slide_3.jpg" alt = "" onload = "slideLoaded(this)" / >

< / div >

W JavaScript użyjemy funkcji slideLoaded() do śledzenia ładowania obrazów i uruchomimy naszą wtyczkę, gdy będzie gotowa:

funkcja slideLoaded(img)( var $img = $(img), $slideWrapper = $img.parent(), total = $slideWrapper.find("img").length, percentLoaded = null; $img.addClass("załadowano "); var załadowany = $slideWrapper.find(.loaded").length; if(loaded == total)( percentLoaded = 100; // INICJALIZACJA WTYCZKI $slideWrapper.easyFader(); ) else ( // ŚLEDŹ WTYCZKĘ PROCES Załadowany procent = załadowany/całkowity * 100; ); );

funkcja slideLoaded(img) (

zmienna $img = $(img) ,

$slideWrapper = $obraz. rodzic(),

suma = $slideWrapper . znajdź („img”). długość,

procent załadowania = null;

$obraz addClass("załadowano");

var załadowany = $slideWrapper . znajdź(.załadowano"). długość ;

if (załadowano == łącznie ) (

procent załadowania = 100;

// INICJALIZUJ WTYCZKĘ

$slajdWrapper. łatwyFader();

) w przeciwnym razie (

// ŚLEDŹ PROCES

procentZaładowany = załadowany / łącznie * 100;

Za każdym razem, gdy ładujemy materiał, dodajemy do niego załadowaną klasę, aby śledzić jego postęp.
Z ostatnim, jeśli zainicjujemy wtyczkę (w w tym przypadku jQuery EasyFader), gdy liczba obrazów z załadowaną klasą jest równa całkowitej liczbie obrazów w kontenerze. Jak dodatkowa nieruchomość Możesz podzielić załadowaną zmienną na zmienną całkowitą i użyć jej do wizualizacji postępu dla użytkowników, wyświetlając wartość procentową, używając jej do kontrolowania szerokości paska postępu lub w inny podobny sposób.

Ponownie, ten skrypt powinien zostać umieszczony w nagłówku dokumentu, po jQuery i dowolnej wtyczce, którą będziesz przetwarzał, gdy będzie gotowy.

3. Wstępne buforowanie obrazów w celu zwiększenia szybkości

Na stronach z duża ilość obrazów, możesz nieznacznie zmniejszyć obciążenie podczas pobierania obrazów za pomocą ładowanie w tle obrazy do pamięci podręcznej przeglądarki, podczas gdy użytkownik porusza się po stronie.

Załóżmy na przykład, że mam witrynę wielostronicową, w której na górze każdej strony dodatkowej znajduje się obraz wysoka rozdzielczość. Zamiast kazać użytkownikowi czekać na załadowanie wszystkich obrazów za każdym razem, gdy do niego przejdzie osobna strona, możesz załadować je do pamięci podręcznej, zanim użytkownik dotrze na stronę. Zacznijmy od umieszczenia ich adresów URL w tablicy:

var heroArray = [ "/uploads/hero_about.jpg", "/uploads/hero_history.jpg", "/uploads/hero_contact.jpg", "/uploads/hero_services.jpg" ]

var bohaterArray = [

"/uploads/hero_about.jpg" ,

"/uploads/hero_history.jpg" ,

"/uploads/hero_contact.jpg" ,

„/uploads/hero_services.jpg”

Zwykle korzystam z mojego systemu CMS lub innego zaplecza, na którym buduję witrynę, aby przekazać te dane na samą stronę w postaci znacznika skryptu w stopce. W ten sposób lista obrazów może być dynamicznie aktualizowana i rozszerzana.

Kiedy użytkownik dotrze na stronę główną mojej witryny, będę na niego czekać załadowany do pełna, zanim cokolwiek zrobisz, aby upewnić się, że nie zakłócam ładowania zawartości samej strony, dodając ładowanie strony trzeciej. Aby to zrobić, dołączę funkcję JavaScript do zdarzenia ładowania okna, które będzie uruchamiane tylko wtedy, gdy cała zawartość strony została już załadowana i wyrenderowana (w tym obrazy), w przeciwieństwie do zdarzenia gotowości dokumentu, które uruchamia się natychmiast po DOM jest gotowy:

funkcja preCacheHeros())( $.each(heroArray, funkcja())( var img = nowy obraz(); img.src = this; )); ); $(okno).load(funkcja())(preCacheHeros(); ));

funkcja preCacheHeros() (

$. każdy(heroArray, funkcja()(

var img = nowy obraz();

obraz. src = to;

} ) ;

$(okno). obciążenie(funkcja()(

preCacheHeros();

} ) ;

Lub z prostym JavaScriptem:

funkcja preCacheHeros())( for(i = 0; i< heroArray.length; i++){ var url = heroArray[i], img = new Image(); img.src = url; }; }; window.onload = preCacheHeros();

funkcja preCacheHeros() (

dla (i = 0 ; tj< heroArray . length ; i ++ ) {

var url = heroArray[i],

img = nowy obraz();

obraz. źródło = adres URL;

okno. onload = preCacheHeros () ;

Używając pętli, iterujemy po obiekcie heroArray, tworząc w każdej iteracji pusty obiekt obrazu, a następnie ustawiamy adres URL na atrybut src naszego obrazu. Spowoduje to załadowanie obrazu do pamięci podręcznej przeglądarki na potrzeby bieżącej sesji, dzięki czemu gdy użytkownik faktycznie odwiedzi stronę, na której prezentowany jest obraz, pojawi się on natychmiast.

Niestety, chociaż praktyka wstępnego buforowania przyspiesza czas ładowania i poprawia komfort użytkownika po stronie klienta, w rzeczywistości zwiększa obciążenie serwera. W takim przypadku warto rozważyć analizę swojej witryny przed wykonaniem wstępnego buforowania. Jeśli większość Twoich użytkowników odwiedza strona główna Twojej witryny i opuszczenia jej przed odwiedzeniem stron drugorzędnych, koszt dodatkowe prośby do Twojego serwera może przewyższyć korzyści oferowane nielicznym użytkownikom, którzy pozostali.

Przed wdrożeniem wstępnego buforowania warto rozważyć analizę witryny

Prekognitywne precaching

Jeśli jednak naprawdę chcesz korzystać z buforowania wstępnego, zalecam podzielenie obrazów na nie znaczące grupy, strategicznie umieszczone na stronie. Na przykład, wiedząc, że zdecydowana większość użytkowników, którzy pozostaną w witrynie, po odwiedzeniu strony głównej przejdzie na stronę dodatkową, wstępnie buforowałbym obrazy strony głównej strony dodatkowej, gdy znajdują się one na stronie głównej.

Załóżmy jednak, że każdy z moich wpisów na blogu również ma obraz w wysokiej rozdzielczości. Wstępne buforowanie ich, gdy użytkownik jest na stronie głównej, będzie nie tylko dużym sukcesem po stronie serwera, ale może również być stratą zasobów, ponieważ, powiedzmy, tylko 15% użytkowników odwiedzających stronę główną kliknie, aby przejść do wpis na blogu. Najlepszym miejscem do wstępnego buforowania obrazów na blogu może być strona docelowa, jeśli wiesz, że prawie wszyscy użytkownicy przejdą stamtąd do wpisu na blogu.

Nazywa się to prekognitywnym buforowaniem wstępnym, w którym wykorzystujemy statystyki z naszych analiz do przewidywania wzorców zachowań, gdy nasi użytkownicy poruszają się po witrynie. Może to brzmieć trochę fantastycznie, ale będziesz zaskoczony, jak dokładnie możesz przewidzieć przepływ odwiedzających i zamienić go w przewagę swoją (i swoich użytkowników).

Może to brzmieć trochę fantastycznie, ale będziesz zaskoczony, jak dokładnie możesz przewidzieć przepływ odwiedzających

4. Leniwe ładowanie obrazów w celu zmniejszenia obciążenia serwera

Koncepcja leniwego ładowania odnosi się do ładowanych obrazów programowo po specjalnym zdarzeniu, aby uniemożliwić przeglądarce żądanie i wyświetlenie wszystkich obrazów na stronie zaraz po załadowaniu dokumentu.

Używane głównie na długich stronach lub stronach zawierających dużo obrazów. NA wstęp W Barrel Blog łączymy leniwe ładowanie z wtyczką MixItUp, aby mieć pewność, że obrazy, które nie znajdują się w bieżącym filtrze lub stronie, nie będą niepotrzebnie ładowane, dopóki ten element nie będzie widoczny. Wszystkie obrazy, które podlegają leniwemu ładowaniu, ponownie zawiniemy w div z klasą img_wrapper, która z kolei otrzyma klasę lazy_load, abyśmy mogli łatwo je wybierać za pomocą jQuery:

) . obciążenie(funkcja()(

leniwe ładowanie();

Powyższa funkcja leniwie ładuje wszystkie obrazy po uruchomieniu zdarzenia ładowania okna, ale kod wewnątrz pętli .each() można dostosować do różnych sytuacji. Bardzo częstym zastosowaniem tego jest dołączenie do zdarzenia przewijania okna i leniwe ładowanie obrazów podczas przewijania do rzutni.

Przejdź do przesyłania zdjęć

W trakcie eksperymentowania z kilkoma z tych technik w różnych projektach przez ostatnie 12 miesięcy, musiałem naprawdę je okroić i udoskonalić do wykorzystania w niedawno przeprojektowanym projekcie Barny.com (wydanym z powrotem do świata w kwiecień), gdzie zastosowałem kombinację wszystkich czterech technik, aby zapewnić płynne ładowanie obrazów, próbując jednocześnie wycisnąć każdy gram wydajności z witryny internetowej zawierającej niezwykle dużo zdjęć i obrazów. Łącząc buforowanie wstępne i leniwe ładowanie z ładowaniem strony o godz Pomoc AJAX-owa, pokazy slajdów i paginacja po stronie klienta, udało nam się stworzyć wspaniałe wrażenie płynności i ogólnej witryny.

Próbując przedstawić te techniki na potrzeby prezentacji prowadzonej przez zespół programistów Barrel, byłem mile zaskoczony, jak lekkie są te techniki na papierze — zwykle 5–10 linii kodu w jQuery — i jak łatwo można je wdrożyć w dowolnym projekcie. Ponadto każdy z nich można bez zbędnych kłopotów napisać przy użyciu prostego JavaScriptu dodatkowy kod, ale jeśli używasz jQuery, jak to często robimy, zdecydowanie powinieneś skorzystać z jego niezawodnych technik przechodzenia przez DOM.

Techniki te są oczywiście jedynym sposobem na wykonanie odpowiednich funkcji, ale można je łatwo dostosować do istniejących frameworków i wtyczek. Jeśli jeszcze nie zastanawiałeś się nad przesłaniem zdjęć, mam nadzieję, że zrobisz to teraz! Dlaczego nie zastosować jednego lub dwóch z nich w swoim następnym projekcie?

  • Tłumaczenie
  • Instruktaż

Szybkie i płynne ładowanie obrazów jest jednym z ważnych elementów dobrego interfejsu internetowego. Ponadto pojawia się coraz więcej witryn wykorzystujących w projektowaniu duże zdjęcia, przy takich projektach szczególnie ważne jest monitorowanie prawidłowego ładowania grafiki. W tym artykule opisano kilka technik, które pomogą Ci kontrolować ładowanie obrazu.

Korzystanie z kontenera na każdy obraz Prosta metoda, którą można zastosować do dowolnego obrazu w serwisie. Sztuczka polega na tym, że każdy obraz jest zawinięty w DIV, co zapobiega ładowaniu wiersz po wierszu:


Za pomocą kontenera możesz kontrolować proporcje obrazu, a także korzystać ze wskaźnika ładowania, co jest bardzo wygodne, jeśli obrazy są ciężkie.

Na przykład, aby ustawić współczynnik proporcji na 4:3, możesz użyć następującego CSS:

Img_wrapper( pozycja: względna; górna część dopełnienia: 75%; przepełnienie: ukryta; ) .img_wrapper img( pozycja: bezwzględna; góra: 0; szerokość: 100%; krycie: 0; )
Aby obraz wyświetlał się w przeglądarce dopiero po jego pełnym załadowaniu należy dodać zdarzenie ładowania dla obrazu i użyj JavaScript, który obsłuży wydarzenie:


funkcja imgLoaded(img)( var $img = $(img); $img.parent().addClass("załadowano"); );
Kod funkcji wewnątrz znacznika HEAD należy umieścić na samym końcu, po dowolnej wtyczce jQuery lub innej wtyczce. Po całkowitym załadowaniu obrazu należy go wyświetlić na stronie:

Img_wrapper.loaded img( krycie: 1; )
Dla efektu gładki wygląd obrazy, których możesz użyć przejścia CSS3:

Img_wrapper img( pozycja: absolutna; góra: 0; szerokość: 100%; krycie: 0; -webkit-przejście: krycie 150 ms; -moz-przejście: krycie 150 ms; -ms-przejście: krycie 150 ms; przejście: krycie 150 ms; )
Dostępny jest żywy przykład tej metody.

Korzystanie z kontenera na wiele obrazów Poprzednia metoda sprawdza się dobrze w przypadku pojedynczych obrazów, ale co jeśli na stronie jest ich wiele, np. galeria zdjęć lub slider? Nie zaleca się przesyłania wszystkiego na raz – zdjęcia mogą sporo ważyć. Aby rozwiązać ten problem, możesz zmusić JavaScript do załadowania tylko tego, czego potrzebujesz ten moment czas obrazu. Przykładowy znacznik HTML dla pokazu slajdów:


Do sterowania procesem używamy funkcji slideLoaded():

Funkcja slideLoaded(img)( var $img = $(img), $slideWrapper = $img.parent(), total = $slideWrapper.find("img").length, percentLoaded = null; $img.addClass("załadowano "); var załadowany = $slideWrapper.find(.loaded").length; if(loaded == total)( percentLoaded = 100; // INSTANTIATE PLUGIN $slideWrapper.easyFader(); ) else ( // ŚLEDZENIE POSTĘPU procentLoaded = załadowano/ogółem * 100; ); );
Załadowanym obrazom przypisuje się załadowaną klasę i wyświetlany jest ogólny postęp. Ponownie JavaScript powinien zostać umieszczony na końcu znacznika HEAD, po wszystkim innym.

Buforowanie W witrynach obciążonych grafiką jest to możliwe tło niezauważone przez użytkownika ładują obrazy do pamięci podręcznej przeglądarki. Na przykład na jednej z nich znajduje się wielostronicowa witryna internetowa strony wewnętrzne który zawiera dużo treści graficznych. W takim przypadku wskazane byłoby załadowanie obrazów do pamięci podręcznej jeszcze przed przełączeniem się użytkownika żądaną stronę. adresy obrazów w tablicy:

var heroArray = [ "/uploads/hero_about.jpg", "/uploads/hero_history.jpg", "/uploads/hero_contact.jpg", "/uploads/hero_services.jpg" ]
Kiedy użytkownik wchodzi na stronę, po załadowaniu strona główna, obrazy zaczynają być ładowane do pamięci podręcznej. Aby mieć pewność, że buforowanie nie zakłóca wyświetlania bieżącej treści, musisz dodać funkcjonalność JavaScript do zdarzenia ładowania okna:

Funkcja preCacheHeros())( $.each(heroArray, funkcja())( var img = nowy obraz(); img.src = this; )); ); $(okno).load(funkcja())(preCacheHeros(); ));
Ta metoda poprawia użyteczność witryny, ale powoduje dodatkowe obciążenie serwera. Należy o tym pamiętać wdrażając taką funkcjonalność. Ponadto należy wziąć pod uwagę możliwe sposoby odwiedzających witrynę i buforuje obrazy znajdujące się na stronach, które użytkownik najczęściej odwiedza. Aby zrozumieć takie ścieżki po witrynie, należy przeanalizować statystyki ruchu.

Ładowanie metodą zdarzenia polega na tym, że obrazy zaczynają się ładować później pewne wydarzenie. Zwiększa to produktywność i oszczędza ruch użytkowników. znaczniki HTML:


Warto zauważyć, że adres URL obrazu jest określony w data-src, a nie src. Jest to konieczne, aby przeglądarka nie pobrała obrazu od razu. Zamiast tego src jest ładowany przezroczystym pikselem GIF base64, co zmniejsza liczbę podróży w obie strony do serwera.

Pozostaje tylko zmienić wartość src na data-src, gdy wystąpi żądane zdarzenie. JavaScript pozwala na stopniowe ładowanie obrazów:

Funkcja lazyLoad())( var $images = $(.lazy_load"); $images.each(function())( var $img = $(this), src = $img.attr("data-src") ; $ img .on("load",imgLoaded($img)) .attr("src",src); )); ); $(okno).load(funkcja())( lazyLoad(); );

Wniosek Nie ma jednego Najlepszym sposobem w celu zarządzania ładowaniem zdjęć na stronie. W każdym konkretny przypadek konieczne jest wybranie odpowiedniej metody, a także połączenie kilku, jeśli to konieczne. Jednym z głównych punktów, na które należy zwrócić uwagę, jest wydajność i ruch. Krótko mówiąc, przede wszystkim powinieneś pomyśleć o tym, jak to będzie wygodniejsze dla użytkownika strona.

Główną zaletą serwisu są dobre i wysokiej jakości zdjęcia. Jednak głównym problemem związanym z używaniem obrazów jest ich rozmiar: zazwyczaj stanowi on co najmniej 50% rozmiaru serwisu, a na każdej stronie znajduje się co najmniej 300 KB obrazów (jest to ilość informacji na telefon komórkowyŁaduje się w około 1,5 sekundy komputer stacjonarny- 0,2-0,3 sekundy).

Co z nimi zrobić?

Obrazy sekwencyjne i PNG

Problem rozmiaru obrazu jest już bardzo stary i dobrze zbadany. Najlepsze, co możesz teraz zrobić, to użyć progresywnego (sekwencyjnego) formacie JPEG dla pełnokolorowych obrazów (zdjęć) i formacie PNG dla wszystkich innych plików (np. obrazy tła lub ikony).

Obrazy sekwencyjne pozwalają na jak najszybsze wyświetlenie istoty obrazu: są ładowane sekwencyjnie od użytkownika, stopniowo poprawiając jakość obrazu. To jest najlepszy wybór podczas korzystania z pełnokolorowych obrazów na wszystkich urządzeniach - od telefonów komórkowych i tabletów po zwykłe komputery.

Wymagany format PNG maksymalna kompresja palety i reprezentacje indeksowanych obrazów (z małą liczbą kolorów) mogą przekazać nawet duży obraz z niewielką ilością informacji. Ma to ogromne znaczenie dla skuteczności Twojej witryny: jeśli nie możesz obniżyć jakości prezentowanych informacji, możesz zmniejszyć ich rozmiar do minimum.

Leniwy ładunek

Kolejnym krokiem w optymalizacji wielkości pobieranych informacji było pobranie obrazów niezbędnych jedynie do wyświetlenia pierwszego ekranu serwisu. Na przykład, jeśli masz katalog zawierający dziesiątki pozycji, ale na pierwszym ekranie mieści się tylko 8, rozsądnie byłoby przesłać najpierw tylko 8 zdjęć. To (wizualnie) znacznie przyspieszy pełne ładowanie strony witryny. A kiedy użytkownik przewinie stronę dalej, ładuje wszystkie obrazy z dalszych części strony. Jednocześnie pokaż wskaźnik ładowania w miejscu ładujących się obrazów.

Istnieje wielka ilość rozwiązania, które w ten czy inny sposób implementują tę metodę - lazyload - możesz łatwo znaleźć wtyczkę, która Ci odpowiada i możesz ją zainstalować. Takie podejście ma jednak kilka wad: użytkownik musi poczekać podczas przewijania strony, aż załadują się „odroczone” obrazy, a implementacja wtyczki może nie być do końca poprawna, co doprowadzi do spowolnienia działania witryny wszystkie urządzenia. Dodatkowo musisz upewnić się, że obrazy w kodzie strony są dostępne dla robotów wyszukujących.

Nie jest to łatwe zadanie, prawda?

Poprawa leniwego obciążenia

Istnieje kilka implementacji lazyload - w szczególności odsłonięcie - które ominęły pierwszą wadę: ładowanie obrazów można opóźnić dokładnie do momentu, w którym pokażemy użytkownikowi „gotową” witrynę (zwykle jest to moment, w którym jest gotowa struktura strony - DOMready - ale czasami strona jest całkowicie załadowana - onload). Zaraz po tym wydarzeniu zaczniemy ładować wszystkie obrazy. Jeśli użytkownik poświęci 2-3 sekundy na wstępne zapoznanie się z zawartością strony, ładowanie obrazów przejdzie prawie niezauważone (przeglądarka już pokaże, że strona jest gotowa). Jeśli mimo wszystko użytkownik zdoła rozpocząć przeglądanie strony przed załadowaniem wszystkich obrazków, wówczas w miejscu obrazów, zamiast domyślnej ikony przeglądarki lub pustego miejsca, pojawi się wskaźnik ładowania.

To dość eleganckie rozwiązanie, ale można je jeszcze ulepszyć, jeśli dokładniej podejdziesz do kolejności ładowania stron serwisu. Zastanów się, które widżety są ładowane i kiedy: aby nie zakłócały procesu ładowania obrazu. Umieść obrazy na 1-2 subdomenach, jeśli jest ich więcej niż 30 - będzie to miało pozytywny wpływ na równoległe ładowanie obrazów. Możliwe jest przeniesienie części obrazów do zdarzenia pełnego ładowania, a części do zdarzenia gotowości struktury strony. Ogólnie rzecz biorąc, sprawdź bardziej szczegółowo proces ładowania witryny i zoptymalizuj doświadczenie użytkownika - tak, aby witryna wyglądała na reaktywną.

Wstępne ładowanie obrazów (pobieranie wstępne)

Społeczność techniczna nie poprzestała na tym i poszła dalej w optymalizacji procesu ładowania obrazów. A co jeśli potrafimy przewidzieć kolejne działania użytkownika na stronie – i od razu załadować potrzebne zasoby (a najważniejszymi z nich są obrazy)? Jak mogę to zrobić?

Technika wstępnego ładowania obrazów (wstępnego ładowania lub pobierania wstępnego) jest aktywnie wykorzystywana w różnych galeriach obrazów - na przykład Yandex.Photos - podczas przeglądania jednego obrazu przeglądarka ładuje już dwa lub trzy poprzednie i dwa lub trzy następne. I pokaże je niemal natychmiast po przejściu do tyłu lub do przodu. I będzie reaktywnie!

W przypadku sklepu internetowego możesz zastosować tę samą technikę podczas przeglądania poszczególnych produktów - od razu ładując zdjęcia z galerii lub podobne produkty z usługi rekomendacji. Spowoduje to zmniejszenie głośności przesyłane informacje z witryny do użytkownika po przejściu nowe łącze i wizualnie przyspieszyć witrynę.

Podsumowanie i lista działań

Zatem masa przydatna informacja. Co dokładnie powinniśmy zrobić? Musisz przejrzeć poniższą listę i sprawdzić, czy na Twojej stronie wszystko jest w porządku. Jeśli nie, podejmij odpowiednie kroki:

  • Czy obrazy w pełnym kolorze są tworzone w sekwencyjnych plikach JPEG? Jeśli nie i możesz zapisywać obrazy z utratą jakości, musisz skonfigurować ten format.
  • Czy wszystkie pozostałe obrazy są w formacie PNG? Jeśli nie, musisz skonfigurować ten konkretny format. Dodatkowo zaleca się optymalizację obrazów PNG partiami lub przy użyciu usług.
  • Czy wszystkie obrazy są wyświetlane w naturalnych rozmiarach? Często Wymiary fizyczne(wysokość i szerokość) obrazu większy rozmiar widoczny obraz. Prowadzi to do podstawowej jakości i zmusza do pobrania znacznie większej ilości danych, niż jest to konieczne. Zmień rozmiar obrazów do tych używanych na stronie (w razie potrzeby utwórz duplikaty w innych rozmiarach).
  • Czy na stronie jest więcej niż 20 obrazów i nie mieszczą się one na pierwszych dwóch ekranach? Aby zmniejszyć ilość początkowo ładowanych informacji, należy zastosować rozwiązanie typu lazyload.
  • Czy oprócz obrazów witryna wykorzystuje kilka widżetów i kodów statystycznych? Sprawdź wykres ładowania swojej witryny, aby upewnić się, że wartościowe obrazy ładujące się z opóźnieniem zostaną najpierw dostarczone użytkownikowi.
  • Chcesz maksymalnie przyspieszyć swoją stronę internetową, a wszystkie kroki zostały już wykonane? Skonfiguruj wstępne ładowanie obrazów podczas nawigacji po stronach witryny. Przestudiuj scenariusze korzystania z witryny i dostosuj do nich logikę ładowania obrazów.
  • To w zasadzie wszystko. Warto przypomnieć, że Airi automatycznie zmniejsza obrazy do minimalnego rozmiaru i najlepszy format bez utraty jakości, a także można je dynamicznie ustawiać prawidłowe rozmiary dla obrazów i opóźnić ich ładowanie.