Grafika na stronie

Jeżeli wrzucasz na stronę zdjęcia z aparatu, warto wcześniej pozbyć się informacji EXIF. Zawierają one informacje kiedy i gdzie zostało wykonane zdjęcie, więc dzięki nim łatwo ciebie namierzyć. I ja popełniłem w tym kursie taki błąd, aż jeden z użytkowników zwrócił mi na to uwagę (za co bardzo dziękuję). W Windowsie wystarczy kliknąć prawym klawiszem na zdjęcie i wybrać właściwości. W zakładce szczegóły na dole będzie link, który umożliwi ci usunięcie niepotrzebnych danych.
Możesz też skorzystać z licznych czyścicieli. Wystarczy w internecie poszukać frazy "exif remove".

Przypuśćmy, że mamy obrazek img na stronie:

Kartofel w wietnamie


    <img src="./wietnam.jpg" class="img" alt="Kartofel w wietnamie" width="353" height="367">

Żeby móc na nim pracować, pobierzmy go i zbadajmy w konsoli (zrób to teraz):


const img = document.querySelector(".img");
console.dir(img);
Widok części debuggera po zbadaniu grafiki

Podobnie jak inne elementy i nasza grafika udostępnia nam masę metod i właściwości, które będą nam pomocne.

Wśród nich jednymi z najczęściej używanymi są:

width szerokość grafiki,
height wysokość grafiki,
alt alternatywny opis grafiki (widoczny gdy się nie wczyta),
title tekst, który pojawi się po najechaniu kursorem na element,
src adres do grafiki

const obr = document.querySelector(".img");
console.log(`Szerokość: ${img.width}, wysokość: ${img.height}, src: ${img.src}`);

Konstruktor Image()

W Javascript obrazki możemy tworzyć na kilka sposobów. Można tutaj wykorzystać np. document.createElement("img"), ale też możemy skorzystać z konstruktora Image(). Przyjmuje on dwa opcjonalne parametry określające szerokość i wysokość.


const img = new Image();
img.src = "test.jpg";

//lub
const img = document.createElement("img");
img.src = "test.jpg";

Stworzona w ten sposób grafika jest ściągana na urządzenie użytkownika, co bardzo przydaje się w momencie, gdy chcemy zawczasu wczytać daną grafikę.

Zdarzenie load

Obiekty wczytywane (np. window, image, iframe itp.) posiadają zdarzenie load, które wykrywa, czy dany obiekt został w pełni załadowany.

Dla obiektu window zdarzenie to oznacza wczytanie całego dokument dom oraz wszystkich grafik (w przeciwieństwie do DOMContentLoaded, które odpalane jest po wczytaniu drzewa DOM, ale przed wczytaniem grafik).
Dla grafiki oznacza to wczytanie danej grafiki:


img.addEventListener("load", e => {
    console.log("Dana grafika została załadowana");
});

img.src = "lorem.jpg"; //wpierw ustawiamy zdarzenie, potem ustawiamy src

Jeżeli w powyższym skrypcie zdarzenie load ustawilibyśmy po ustawieniu src, skrypt mógł by zadziałać nieprawidłowo. Może zdarzyć się sytuacja, że obrazek wczyta się natychmiastowo po ustawieniu src (np. siedzi już w cache przeglądarki). Oznacza to, że obrazek wczyta się przed odpaleniem nasłuchiwania zdarzenia load.

Są jednak sytuacje (szczególnie przy bardziej skomplikowanych systemach), że nie jesteśmy w stanie zagwarantować takiej kolejności. Przykładowo system pobiera sobie src grafik, a podpięcie zdarzeń następuje dopiero później. W takim przypadku warto sprawdzić właściwość complete każdej grafiki, która wskazuje czy dany obrazek jest wczytany czy nie. Jeżeli tak się stanie odpalimy dla niej zdarzenie load.


img.src = "lorem.jpg";

img.addEventListener("load", e => {
    console.log("Dana grafika została załadowana");
});

if (img.complete) {
    const loadEvent = new Event("load");
    img.dispatchEvent(loadEvent);
}

Postęp wczytywania grafik na stronie

Wyobraź sobie, że naszym zadaniem będzie zrobienie paska ładowania grafik użytych na stronie.

Aby to zrealizować, zacznijmy od przygotowania elementu z paskiem postępu:


.loading-bar {
    margin: 30px 0;
    height: 10px;
    border-radius: 10px;
    background: #eee;
    display: flex;
    overflow:hidden;
}

.loading-bar__progress {
    background: tomato;
}

<div id="loading-bar">
    <div class="loading-bar__progress"></div>
</div>

Sam skrypt będzie raczej prosty. Tworzymy tablicę ze ścieżkami do grafik oraz pustą tablicę, do której będziemy wrzucać obiekty typu Images, które będą miały ustawione src takie jak poszczególne elementy w tablicy.


//tablica z nazwami obrazków do załadowania
const imgNames = [
    "obrazek1.gif",
    "obrazek2.gif",
    "obrazek3.gif",
    "obrazek4.gif",
    "obrazek5.gif",
    "obrazek6.gif"
];

const loadingStep = (100 / imgNames.length); //szerokość oznaczająca % paska po załadowaniu 1 obrazka

const images = []; //tablica będzie zawierała obiekty Image

const loading = document.querySelector(".loading");
const loadingBar = loading.querySelector(".loading-progress");

//funkcja rozpoczynająca ładowanie obrazków
function startLoading(cb) {
    imgNames.forEach(name => {
        const img = new Image();
        //po wczytaniu grafiki wrzucam nowe Image() do tablicy images
        //sprawdzam ile elementów ma ta tablica i na tej podstawie ustawiam szerokość paska postępu

        img.addEventListener("load", e => {
            images.push(img);
            loadingBar.style.width = `${images.length * loadingStep}%`; //zmieniamy szerokość paska w %

            if (images.length >= imgNames.length) {
                cb(); //odpalam jakąś funkcję po zakończeniu wczytywania
            }
        });
        img.src = name;

        if (img.complete) {
            img.dispatchEvent(new Event("load"));
        }
    });
}

startLoading(function() {
    alert("Zakończono wczytywanie")
});

Powyższy przykład możesz zobaczyć w działaniu tutaj.

Jak zauważysz, takie wczytywanie działa "skokowo" ponieważ zmianę paska dokonujemy dopiero po wczytaniu danej grafiki. Przy dużej liczbie małych grafik nie powinno to być problemem, ale co jeżeli wczytujemy bardzo duże grafiki? W tym repozytorium znajdziesz moją małą próbę rozwiązania tego problemu. Polecam przetestować przy ograniczeniu szybkości łącza w zakładce Network debuggera.

Lazy loading

Lazy loading to metoda wczytywania obrazków polegająca na tym, że dany obrazek wczytywany jest dopiero w momencie gdy pojawi się na ekranie.

W nowych przeglądarkach wczytywanie takie możemy uzyskać za pomocą dodatkowego atrybutu lazy dla elementów img:


<img src="image.png" loading="lazy" alt="...">
<iframe src="https://example.com" loading="lazy"></iframe>

Atrybut ten może przyjąć jedną z wartości:

auto domyślna wartość dla leniwego wczytywania. Równa temu, jakbyśmy w ogóle tego atrybutu nie używali.
lazy opóźnione wczytywanie grafiki gdy osiągnie ona wskazany dystans od ekranu (zależy od typu zasobów, szybkości łącza itp.)
eager zdjęcie ma być wczytywane natychmiast po wejściu na stronę

W przypadku, gdy dana przeglądarka nie obsługuje powyższego atrybutu, możemy skorzystać z kilku metod naprawy tego stanu.

Pierwszą z nich jest użycie tak zwane IntersectObserver, który nasłuchuje, czy dane elementy znalazły się w zadanym obszarze.

Drugą jest użycie jednego z zdarzeń resize, scroll i ewentualnie orientationchange.

Nie będę tutaj duplikował czyjegoś kodu i zwyczajnie odeślę was pod ten adres, gdzie został pokazany stosowny kod.

Wszelkie prawa zastrzeżone. Jeżeli chcesz używać jakiejś części tego kursu, skontaktuj się z autorem.
Aha - i ta strona korzysta z ciasteczek.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.