Grafika na stronie
Możesz też skorzystać z licznych czyścicieli. Wystarczy w internecie poszukać frazy "exif remove".
Przypuśćmy, że mamy obrazek img na stronie:
<img src="./wietnam.jpg" class="img" alt="Kartofel w wietnamie" width="400" height="400">
Żeby móc na nim pracować, pobierzmy go i zbadajmy w konsoli (zrób to teraz):
const img = document.querySelector(".img");
console.dir(img);

Jak widzisz w konsoli debugera (mam nadzieję, że masz ją otwartą), dla tak pobranej grafiki możemy ustawiać mnóstwo właściwości i korzystać z wielu metod.
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}`);
No dobrze - w praktyce używa się tego co pasuje w danej sytuacji. Poniżej zajmiemy się częstymi przypadkami, które są spotykane przy pracy z grafiką w js.
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";
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 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 eventu load.
Są jednak sytuacje (szczególnie przy bardziej skomplikowanych skryptach), że nie jesteśmy w stanie zagwarantować takiej kolejności. Przykładowo system podpina wszystkie eventy, a gdzieś dalej dopiero budowane są src grafik w systemie. 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) {
//odpalam ręcznie event load
img.dispatchEvent(new Event("load"));
}
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ć elementy 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.
Wczytywanie grafiki i obietnice
Wczytywanie to proces asynchroniczny, więc jest to idealne miejsce by zastosować obietnice lub async/await.
Napiszmy prostą funkcję, która zwróci nam obietnicę, który zostanie rozwiązany gdy grafika zostanie wczytana. W przeciwnym razie zostanie zwrócony błąd. Tak naprawdę są to powyżej zebrane informacje okryte za pomocą Promise:
function loadImage(name, src) {
return new Promise((resolve, reject) => {
const img = new Image();
//zwracamy obiekt, który będzie miał 2 klucze:
//name - nazwa którą będziemy podawać przy odwoływaniu się do tej grafiki
//img - właściwy element img, który będzie zwracany
img.addEventListener("load", () => resolve({name : name, img : img}));
img.addEventListener("error", e => reject(e));
img.src = src;
if (img.complete) {
const event = new Event("load");
img.dispatchEvent(event);
}
});
}
Wykorzystajmy ją w funkcji wczytującej kilka grafik na raz:
const graphicCollection = [
{name : "hero" , src : "graphic-to-load/aniolek.jpg"},
{name : "icon" , src : "graphic-to-load/aniolek2.jpg"},
{name : "cats" , src : "graphic-to-load/book.jpg"},
{name : "pies" , src : "graphic-to-load/bum.jpg"}
];
const loadImages = function(sources) {
const promises = sources.map(img => loadImage(img.name, img.src));
return Promise.all(promises);
}
Od tej pory oczekiwanie na wczytanie wszystkich grafik będzie bardzo proste:
loadImages(graphicCollection).then(data => {
//kluczami będą nazwy grafik - np. grafika1, grafika-moja2, grafika-inna3
data.forEach(img => {
images.set(img.name, img.img);
});
console.log("hero -> ", images.get("hero"));
console.log("icon -> ", images.get("icon"));
console.log("cats -> ", images.get("cats"));
console.log("pies -> ", images.get("pies"));
});
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 eventów resize, scroll i orientationchange.
Nie będę tutaj duplikował czyjegoś kodu i zwyczajnie odeślę was pod ten adres, gdzie został pokazany stosowny kod.