Preîncărcarea imaginii. Toate comentariile la nota „Preîncărcarea imaginilor – un exemplu de preîncărcare a imaginilor în HTML, JavaScript”. Încărcare după eveniment

  • Traducere
  • Tutorial

Încărcarea rapidă și lină a imaginilor este una dintre componentele importante ale unei bune interfețe web. În plus, apar tot mai multe site-uri care folosesc fotografii mari în design; pentru astfel de proiecte este deosebit de important să se monitorizeze încărcarea corectă a graficelor. Acest articol descrie mai multe tehnici care vă vor ajuta să controlați încărcarea imaginii.

Folosirea unui container pentru fiecare imagine O metodă simplă care poate fi aplicată oricărei imagini de pe site. Trucul este că fiecare imagine este înfășurată într-un DIV, ceea ce împiedică încărcarea rând cu rând:


Folosind containerul, puteți controla raportul de aspect al imaginii și, de asemenea, puteți utiliza indicatorul de încărcare, care este foarte convenabil dacă imaginile sunt grele.

De exemplu, pentru a seta raportul de aspect la 4:3, puteți utiliza următorul CSS:

Img_wrapper( poziție: relativă; padding-top: 75%; overflow: ascuns; ) .img_wrapper img( poziție: absolut; sus: 0; lățime: 100%; opacitate: 0; )
Pentru a vă asigura că imaginea este afișată în browser numai după ce a fost încărcată complet, trebuie să adăugați un eveniment de încărcare pentru imagine și să utilizați JavaScript pentru a gestiona evenimentul:


funcția imgLoaded(img)( var $img = $(img); $img.parent().addClass("încărcat"); );
Cod de funcție în interior Eticheta HEAD ar trebui să fie situat la sfârșit, după orice jQuery sau alt plugin. După ce imaginea este încărcată complet, aceasta trebuie să fie afișată pe pagină:

Img_wrapper.loaded img( opacitate: 1; )
Pentru efectul unui aspect neted al unei imagini, puteți utiliza tranziția CSS3:

Img_wrapper img( poziție: absolut; sus: 0; lățime: 100%; opacitate: 0; -webkit-tranziție: opacitate 150ms; -moz-tranziție: opacitate 150ms; -ms-tranziție: opacitate 150ms; tranziție: opacitate; 150ms
Un exemplu viu al acestei metode este disponibil.

Utilizarea unui container pentru multe imagini Metoda anterioară funcționează bine pentru imagini individuale, dar dacă sunt multe pe pagină, de exemplu o galerie foto sau un slider? Nu este indicat să încărcați totul deodată - imaginile pot cântări mult. Pentru a rezolva această problemă, puteți forța JavaScript să încarce numai ceea ce aveți nevoie acest moment timpul imaginii. Exemplu de markup HTML pentru o prezentare de diapozitive:


Folosim funcția slideLoaded() pentru a controla procesul:

Funcția slideLoaded(img)( var $img = $(img), $slideWrapper = $img.parent(), total = $slideWrapper.find("img").length, percentLoaded = null; $img.addClass("încărcat "); var loaded = $slideWrapper.find(".loaded").length; if(loaded == total)( percentLoaded = 100; // PLUGIN INSTANTIATE $slideWrapper.easyFader(); ) else ( // TRACK PROGRESS procent Încărcat = încărcat/total * 100; ); );
Imaginilor încărcate li se atribuie clasa încărcată, iar progresul general este afișat. Din nou, JavaScript ar trebui să fie plasat la sfârșitul etichetei HEAD, după orice altceva.

Memorarea în cache Pe site-uri grele din punct de vedere grafic, puteți fundal, neobservat de utilizator, încarcă imagini în memoria cache a browserului. De exemplu, există un site web cu mai multe pagini, pe unul dintre pagini interne care are mult conținut grafic. În acest caz, ar fi recomandabil să încărcați imagini în cache chiar înainte ca utilizatorul să treacă la pagina dorită. adresele imaginilor din matrice:

var heroArray = [ "/uploads/hero_about.jpg", "/uploads/hero_history.jpg", "/uploads/hero_contact.jpg", "/uploads/hero_services.jpg" ]
Când un vizitator intră pe site, după încărcare pagina principala, imaginile încep să fie încărcate în cache. Pentru a vă asigura că stocarea în cache nu interferează cu afișarea conținutului curent, trebuie să adăugați funcționalitate JavaScript la evenimentul de încărcare a ferestrei:

Funcția preCacheHeros())( $.each(heroArray, function())( var img = new Image(); img.src = this; )); ); $(window).load(function())( preCacheHeros(); ));
Această metodă îmbunătățește capacitatea de utilizare a site-ului, dar pune încărcare suplimentară pe server. Acest lucru trebuie reținut atunci când implementați o astfel de funcționalitate. În plus, este necesar să se țină cont moduri posibile vizitatorii site-ului și memorează imaginile situate în paginile pe care utilizatorul este cel mai probabil să le viziteze. Pentru a înțelege astfel de căi prin site, este necesar să analizați statisticile de trafic.

Metoda de încărcare bazată pe evenimente este că imaginile încep să fie încărcate după un anumit eveniment. Acest lucru crește productivitatea și economisește traficul utilizatorilor. Marcaj HTML:


Este de remarcat faptul că adresa URL a imaginii este specificată în data-src, nu în src. Acest lucru este necesar pentru ca browserul să nu descarce imaginea imediat. În schimb, src este încărcat cu un pixel GIF transparent de bază64, ceea ce reduce numărul de călătorii dus-întors la server.

Tot ce rămâne este să schimbați valoarea src în data-src atunci când are loc evenimentul dorit. JavaScript vă permite să încărcați imagini în mod incremental:

Funcția lazyLoad())( var $imagini = $(".lazy_load"); $images.each(function())( var $img = $(this), src = $img.attr("data-src") ; $ img .on(„încărcare”, imgÎncărcat($img)) .attr(„src”,src); )); ); $(window).load(function())( lazyLoad(); );

Concluzie Nu există una cel mai bun mod pentru a gestiona încărcarea imaginilor pe site. În fiecare caz specific, este necesar să alegeți metoda adecvată și, de asemenea, să combinați mai multe, dacă este cazul. Unul dintre punctele principale cărora trebuie să le acordați atenție este performanța și traficul. Mai simplu spus, în primul rând ar trebui să te gândești cum va fi mai convenabil pentru utilizator site-ul.
De ce trebuie să preîncărcăm imaginile? Cel mai adesea îl folosim pentru desenul de înaltă calitate a interfețelor și controalelor site-ului.Exemplu: Există un script de galerie sau blocuri de text cu posibilitatea de a muta (aici/aici). Săgețile grafice sunt responsabile pentru controlul mișcării. Când treceți cu mouse-ul peste o săgeată, imaginea acesteia este înlocuită cu alta.
Ce face browserul la hover? Trimite o cerere de imagine către server. Chiar și cu un răspuns foarte rapid, efectul de „clipire” va fi observat. Dacă preîncărcați imagini, acest lucru nu se va întâmpla aspect modern această abordare este rar folosită. Este mult de preferat să folosiți CSS Sprites. Dar, dacă acest lucru nu este posibil și chiar ai nevoie de el, bine ai venit la pisică.

Var imgPath = "/tpl/images/"; // calea către directorul cu imagini // lista de imagini var preloadImagesList = Array("about_hover.jpg", "news_hover.jpg", "photo_hover.jpg", "video_hover.jpg", "contacts_hover.jpg"); / // ********************************/ // funcția preîncărcare funcția preloadImagini(imagini)( for(var i = 0; i< images.length; i++){ var image = images[i]; $("").attr("src", imgPath + imagine); )//for )//preloadImages /*************************** ********** ****/ //apel de funcție $().ready(function())( preloadImages(preloadImagesList); ))

Pentru a juca jocul trebuie să încărcați aproximativ 12 imagini în avans, iar aceste imagini pot varia de la caz la caz. Adică acum trebuie să încărc vreo 12 imagini (SVG), iar mâine voi avea nevoie de alte 12. Prin urmare, opțiunea de a le plasa în nu este potrivit, deoarece în acest caz va trebui să încărcați în mod constant toate imaginile, iar eu am nevoie doar de 12. Prin urmare, s-a decis să le încărcați folosind JavaScriptînainte de începerea jocului. Pentru a face acest lucru, am implementat o clasă mică „AssetsPreloader”, care, până acum, are singura metoda"preload", care preia o matrice de obiecte de forma (src: "link", id: "id") și se încarcă imaginile necesare de creație ușoară o instanță a clasei Image() (nativă).

Class AssetsPreloader ( static preload(arr) ( arr.map((a)) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. active || ).push(img); )); ) )

Toate imaginile încărcate ajung în proprietatea activelor statice a acestei clase.

Următorul în cod este redarea primului cadru al jocului, unde aceste imagini sunt deja folosite. Și, în general, problema este că redarea nu are loc. Execuția codului ajunge la el, am verificat acest lucru, iar după el se execută codul, dar imaginile în sine nu sunt desenate. Din câte am înțeles, asta se întâmplă pentru că imaginile nu au timp să se încarce (chiar dacă sunt încărcate de pe disc). Cu toate acestea, dacă solicitați să desenați primul cadru direct din consola browserului, atunci totul funcționează așa cum ar trebui și cadrul este desenat normal.

Întregul cod arată în general cam așa:

Class AssetsPreloader ( static preload(arr) ( arr.map((a)) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. active || ).push(img); this.done = true; )); ) ) AssetsPreloader.preload([ (src: "imagini/imagine.svg", id: "id_of_image"), ... ]); // ... GAME.field.draw();

În cele din urmă, întrebarea se rezumă la modul de încărcare a imaginilor (și a diferitelor tipuri de fișiere în general) cât mai corect posibil, astfel încât până când nu sunt încărcate, codul să nu fie executat în continuare. Mai mult decât atât, poate că va exista un fel de bară de progres pe ecran în acest moment (adică nici scriptul nu ar trebui să înghețe complet). Primul lucru care mi-a venit în minte a fost să adaug tot restul codului la apelarea la metoda preload(), dar această idee nu a avut succes.

Te rog ajuta-ma. Interesat nu numai cum, ci și care este cel mai corect mod (cele mai bune practici, toate acestea).

P.S. Fișierul script este conectat la pagina cu atributul defer. Când folosiți, de exemplu, async , redarea are loc sau nu (nu pot spune de ce depinde). Dar nu vreau să adaug handlere pentru verificarea încărcării paginii, pregătirea DOM sau ceva de genul în codul în sine.

Pentru a juca jocul trebuie să încărcați aproximativ 12 imagini în avans, iar aceste imagini pot varia de la caz la caz. Adică acum trebuie să încărc vreo 12 imagini (SVG), iar mâine voi avea nevoie de alte 12. Prin urmare, opțiunea de a le plasa în nu este potrivit, pentru că în acest caz va trebui să încărcați în mod constant toate imaginile, iar eu am nevoie doar de 12. Prin urmare, s-a decis să le încărcați folosind JavaScript înainte de a începe jocul. Pentru a face acest lucru, am implementat o mică clasă „AssetsPreloader”, care, deocamdată, are o singură metodă „preload”, care preia o matrice de obiecte de forma (src: „link”, id: „id”) și încarcă imaginile necesare prin simpla creare a unei instanțe a clasei Image() (nativă).

Class AssetsPreloader ( static preload(arr) ( arr.map((a)) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. active || ).push(img); )); ) )

Toate imaginile încărcate ajung în proprietatea activelor statice a acestei clase.

Următorul în cod este redarea primului cadru al jocului, unde aceste imagini sunt deja folosite. Și, în general, problema este că redarea nu are loc. Execuția codului ajunge la el, am verificat acest lucru, iar după el se execută codul, dar imaginile în sine nu sunt desenate. Din câte am înțeles, asta se întâmplă pentru că imaginile nu au timp să se încarce (chiar dacă sunt încărcate de pe disc). Cu toate acestea, dacă solicitați să desenați primul cadru direct din consola browserului, atunci totul funcționează așa cum ar trebui și cadrul este desenat normal.

Întregul cod arată în general cam așa:

Class AssetsPreloader ( static preload(arr) ( arr.map((a)) => ( let img = new Image(); img.src = a.src; img.id = a.id; (this.assets = this. active || ).push(img); this.done = true; )); ) ) AssetsPreloader.preload([ (src: "imagini/imagine.svg", id: "id_of_image"), ... ]); // ... GAME.field.draw();

În cele din urmă, întrebarea se rezumă la modul de încărcare a imaginilor (și a diferitelor tipuri de fișiere în general) cât mai corect posibil, astfel încât până când nu sunt încărcate, codul să nu fie executat în continuare. Mai mult decât atât, poate că va exista un fel de bară de progres pe ecran în acest moment (adică nici scriptul nu ar trebui să înghețe complet). Primul lucru care mi-a venit în minte a fost să adaug tot restul codului la apelarea la metoda preload(), dar această idee nu a avut succes.

Te rog ajuta-ma. Interesat nu numai cum, ci și care este cel mai corect mod (cele mai bune practici, toate acestea).

P.S. Fișierul script este conectat la pagina cu atributul defer. Când folosiți, de exemplu, async , redarea are loc sau nu (nu pot spune de ce depinde). Dar nu vreau să adaug handlere pentru verificarea încărcării paginii, pregătirea DOM sau ceva de genul în codul în sine.

De ce ai nevoie de imagini? Să ne imaginăm că aveți un element pe pagina unui site web și doriți ca imaginea de fundal a acestuia să fie afișată sau modificată atunci când treceți cu mouse-ul peste el. În principiu, problemele nu ar trebui să apară; totul poate fi rezolvat simplu: atunci când se creează un site în marcajul de stil pentru pseudo-clasa:hover al elementului dorit, specificăm calea către imaginea necesară în proprietatea de fundal.

Dar există o avertizare: dacă evenimentul hover are loc pentru prima dată, atunci poate dura timp pentru a încărca imaginea. Deși acest interval de timp poate fi mic, uneori este posibil să observați o întârziere scurtă și enervantă între trecerea cursorului peste un element și afișarea completă a imaginii. Este clar că în viitor nu vor exista astfel de întârzieri, deoarece browserele vor stoca imaginea în cache cu bună-credință. Dar, după cum știți, prima impresie a site-ului dvs. ar trebui să fie doar pozitivă și nu este nevoie să o stricați cu astfel de fleacuri, mai ales că pot fi evitate. Cum să rezolvi o problemă atât de mică, dar unică? Există multe metode, aici studioul nostru web vă va prezenta doar cele care pot fi rezolvate folosind css.

Prima tehnică este să încărcați imediat componenta grafică și apoi să o eliminați din zona vizibilă folosind proprietatea fundal-position, de exemplu prin setarea următoarelor decalaje x și y - -9999px -9999px. Când are loc evenimentul de hover, aplicăm deja valori reale, de exemplu, în stânga jos.

Ce trebuie făcut dacă elementul are deja imagine de fundal, iar atunci când treceți cursorul mouse-ului, acesta trebuie schimbat. Tehnica de mai sus nu mai este potrivită ca soluție. De obicei, în astfel de cazuri se folosesc sprite-uri (combinate imagini de fundal) când poziția de fundal este deplasată. Dacă această metodă nu vă este disponibilă, încercați următoarele. Aplicați o imagine unui alt element existent pe pagină care nu are o imagine de fundal.

#random-unsuspecting-element ( fundal: url(images/grass.png) no-repeat -9999px -9999px; )

#grass:hover ( fundal: url(images/grass.png) no-repeat; )

Ideea este de a crea elemente noi care sunt necesare doar pentru a preîncărca imaginile. Veți spune că acesta nu este cel mai bun Cel mai bun mod, deoarece numărul de astfel de manechine poate fi uriaș, dar soluția nu va fi elegantă. Și vei avea perfectă dreptate. Nu avem nevoie elemente suplimentare, deoarece le putem folosi pe cele existente cu liniște sufletească. Tot ce ne trebuie este să folosim pseudo-clasele:after sau:before.

#ceva:inainte (

continut: url("./img.jpg");

vizibilitate:ascuns;

Această opțiune ne oferă posibilitatea de a preîncărca imagini fără a crea elemente suplimentare.

Desigur, puteți folosi javascript în aceste scopuri, dar dacă soluțiile de mai sus sunt suficiente pentru a crea un site web, atunci de ce să nu le folosiți.