Powiększanie miniaturki obrazka (lightbox w stylu medium.com)
- Data Publikacji:
- Aktualizacja:
∼ 20 linijek czystego (vanilla) javascript bez dodatkowych bibliotek i mamy powiększanie obrazka à la medium.com z wyjściem awaryjnym gdy javascript jest wyłączony. Dla urozmaicenia kilka wariantów powiększania. Ultra lekki „lightbox” jako przykład połączenia javascript z CSS.
Kod html, css i javascript
HTML
Podstawowy kod html dla miniaturki z powiększeniem. W linku ścieżka do pełnego obrazka, klasa CSS .u-blowUpImg
i zagnieżdżony obrazek miniaturki.
<!-- Link do powiększenia z klasą "u-blowUpImg", przy wyłączonym javascript to wyjście awaryjne (fallback),
powiększony obrazek wyświetli się bez animacji. Dopóki nie klikniemy przeglądarka nie pobierze obrazka. -->
<a class="u-blowUpImg" href="full-size-img.png">
<!-- Miniaturka -->
<img src="thumbnail.png" alt="Image description">
</a>
CSS
.u-blowUpImg:hover {
cursor: zoom-in; /* Kursor przybliżenia */
}
Javascript
Skrypt w sekcji head. Po załadowaniu DOM do każdego elementu z klasą CSS .u-blowUpImg
dodawana jest obsługa kliknięcia z powiększeniem. Na powiększeniu obsługa kliknięcia ukrywającego pełną wersję obrazka. Jeśli obsługa javascript jest wyłączona to powiększenie bez animacji.
Plik powiększania pobiera się po kliknięciu więc w przypadku wolnego połączenia obraz pojawi się w trakcie animacji. Remedium na to dalej.
<script>
// Po załadowaniu strony
document.addEventListener("DOMContentLoaded", function() {
// <div> na powiększoną wersję obrazka jako tło
let backgroundCanvas = document.createElement("div");
// Style CSS. Długość animiacji pow/pom, kursor, środek ekranu, ukrycie.
backgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 50%; width: 0; height: 0; z-index: 1; \
background: rgba(0,0,0,0.9) none center/contain no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
// Dodanie do body jako ostatni element
document.body.appendChild(backgroundCanvas);
// Po kliknięciu w powiększony obrazek zamknięcie powiększenia (width:0; height:0)
backgroundCanvas.onclick = function() {
backgroundCanvas.style.inset = "50% auto auto 50%"; //top right bottom left
backgroundCanvas.style.width = "0";
backgroundCanvas.style.height = "0";
};
// Kolekcja wszystkich elementów (miniaturek) z .u-blowUpImg
let zoomInImgLinks = document.getElementsByClassName("u-blowUpImg");
// Dodanie obsługi kliknięcia na każdej miniaturce
for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
e.preventDefault();// Nie otwieraj linka i użyj javascript do powiększenia
// Pokaż obrazek z href i animuj style (transition: all .8s ease-out;)
backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
backgroundCanvas.style.inset = "0 auto auto 0";
backgroundCanvas.style.width = "100%";
backgroundCanvas.style.height = "100%";
})
})
</script>
Przykłady
Panorama Krakowa
Zdjęcie Dawida Łabno na Unsplash
W powiększeniu to co najlepsze
Zdjęcie Zuza Reinhard na Unsplash
Stadion Narodowy Warszawa
Wersja powiększenia z animacją w trakcie ładowania obrazka. Przy szybkim łączu lub małym pliku animacja jest niewidoczna. Poniżej animowany svg, który ją generuje.
Efekt ładowania obrazka uzyskuje się wykorzystując Image API. Przed wyświetleniem powiększenia tworzymy zmienną na obrazek, ładujemy plik do pamięci i w trakcie pobierania wyświetlamy animowany SVG. Po załadowaniu obrazka przeglądarka wywołuje obsługę zdarzenia „onload” z funkcją wyświetlającą powiększenie. Szczegóły w komentarzu kodu javascript.
Obraz Henryk Niestrój z Pixabay
HTML, CSS, Javascript
<style>
.u-BlowUpImgPreload:hover {
cursor: zoom-in;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var backgroundCanvas = document.createElement("div");
backgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 50%; width: 0; height: 0; z-index: 2; \
background: rgba(0,0,0,0.9) none 50% 50%/contain no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
document.body.appendChild(backgroundCanvas);
// Tło dla animacji podczas ładowania obrazka
var preloaderBackgroundCanvas = document.createElement("div");
// Style
preloaderBackgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 50%; width: 15vmin; height: 15vmin; \
background-repeat: no-repeat; background-position: center; background-size: 100%; z-index: 1; display: none;";
// Animowany svg jako tło zdefiniowany w kodzie żeby nie było problemów z opóźnieniem przy wczytaniu pliku. Przy tak małej wadze istotność pamięci podręczniej znikoma.
preloaderBackgroundCanvas.style.backgroundImage = "url('" + 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" version="1.1" viewBox="0 0 40 40"> \
<title>Obrotowa ćwiartka na obręczy</title> \
<circle cx="20" cy="20" r="16" fill="none" stroke="%23ee4e19" stroke-opacity=".2" stroke-width="5"/> \
<path d="m1.39 20h4.97c0-8.56 7.05-13.6 13.6-13.6v-5.03c-9.99 0-18.6 8.33-18.6 18.6z" fill="%23ee4e19"> \
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 20 20" to="360 20 20" dur="0.6s" repeatCount="indefinite"/> \
</path></svg>' + "')";
document.body.appendChild(preloaderBackgroundCanvas);
// Pełna wersja obrazka
var fullPicture = new Image();
backgroundCanvas.onclick = function() {
backgroundCanvas.style.top = "50%";
backgroundCanvas.style.left = "50%";
backgroundCanvas.style.width = "0";
backgroundCanvas.style.height = "0";
};
var zoomInImgLinks = document.getElementsByClassName("u-BlowUpImgPreload");
for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
e.preventDefault();
// Po załadowaniu obrazka do pamięci wywołanie zdarzenia z funkcją powiększenia.
fullPicture.onload = function() {
preloaderBackgroundCanvas.style.display = "none";
backgroundCanvas.style.backgroundImage = "url(" + fullPicture.src + ")";
backgroundCanvas.style.top = "0";
backgroundCanvas.style.left = "0";
backgroundCanvas.style.width = "100%";
backgroundCanvas.style.height = "100%";
}
// Przypisanie adresu pełnej wersji zdjęcia zawsze wywołuje zdarzenie "onload", nawet jak jest identyczny (wielokrotne kliknięcie)
// Jak w pamięci - wywołuje "onload". Jak nowy - rozpoczyna pobieranie.
fullPicture.src = e.target.parentNode.href;
// Wyświetlenie animacji w trakcie pobierania.
// Jeśli obraz powiększenia w pamięci tylko krótkie błyśnięcie - można wyeliminować dodatkowymi warunkami - pozostawione dla przejrzystości kodu.
preloaderBackgroundCanvas.style.display = "block";
})
})
</script>
<!-- HTML -->
<a class="u-BlowUpImgPreload" href="img/stadion-1398391_1920.jpg">
<img src="img/stadion-1398391_640.jpg" width="640" height="462" alt="Stadion Narodowy, Warszawa">
</a>
<!-- HTML -->
Animowane umilacze oczekiwania na załadowanie obrazka
Kilka przykładowych animowanych obrazów (preloader) SVG wyświetlanych odwiedzającemu w trakcie pobierania powiększania. Po aktualizacjach z dnia i kolory w SVG zdefiniowane jako zmienne CSS (custom properties) i reagują prawidłowo na zmianę trybu wyświetlania.
Warianty wyświetlania powiększenia
Uśmiechnięte oczy
Zdjęcie Michael Dam na Unsplash
HTML, CSS, Javascript
<style>
.u-ShutterUpDown:hover {
cursor: zoom-in;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var backgroundCanvas = document.createElement("div");
backgroundCanvas.style.cssText = "position: fixed; top: 50%; left: 0; width: 100%; height: 0; z-index: 1; background: rgba(0,0,0,0.9) none center/auto 100vmin no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
document.body.appendChild(backgroundCanvas);
backgroundCanvas.onclick = function() {
backgroundCanvas.style.top = "50%";
backgroundCanvas.style.left = "0";
backgroundCanvas.style.width = "100%";
backgroundCanvas.style.height = "0";
};
var zoomInImgLinks = document.getElementsByClassName("u-ShutterUpDown");
for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
e.preventDefault();
backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
backgroundCanvas.style.top = "0";
backgroundCanvas.style.left = "0";
backgroundCanvas.style.width = "100%";
backgroundCanvas.style.height = "100%";
})
})
</script>
<!-- HTML -->
<a class="u-ShutterUpDown" href="img/michael-dam-mEZ3PoFGs_k-unsplash.jpg">
<img src="img/michael-dam-mEZ3PoFGs_k-unsplash-min.jpg" alt="Uśmiechnięta dziewczyna">
</a>
<!-- HTML -->
Przepis na ciasteczka
W powiększeniu pokaz slajdów + przepis. Zmiany zdjęć za pomocą animowanego png (apng). Przy wyłączonym javascript przepis wyświetla się pod miniaturką.
HTML, CSS, Javascript
<style>
.u-DrawTheCurtains:hover {
cursor: zoom-in;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var backgroundCanvas = document.createElement("div");
backgroundCanvas.style.cssText = "position: fixed; top: 0; left: 50%; width: 0; height: 100%; overflow: hidden; text-align: center; z-index: 1; background: rgba(255,255,255,0.95) none center/auto 100vmin no-repeat; transition: all .8s ease-out; cursor: zoom-out;";
backgroundCanvas.innerHTML = document.getElementById("muffinRecipeDetails").innerHTML;//Dodanie html z noscript
document.body.appendChild(backgroundCanvas);
backgroundCanvas.onclick = function() {
backgroundCanvas.style.top = "0";
backgroundCanvas.style.left = "50%";
backgroundCanvas.style.width = "0";
backgroundCanvas.style.height = "100%";
};
var zoomInImgLinks = document.getElementsByClassName("u-DrawTheCurtains");
for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
e.preventDefault();
backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
backgroundCanvas.style.top = "0";
backgroundCanvas.style.left = "0";
backgroundCanvas.style.width = "100%";
backgroundCanvas.style.height = "100%";
})
})
</script>
<!-- HTML -->
<a class="u-DrawTheCurtains" href="img/muffins-animated.png">
<img src="img/muffins-composition-min.png" width="384" height="288" alt="Przygotowanie ciasteczek">
</a>
<span style="font-size: .8em; display: block;">Zdjęcie i wykonanie Dorota</span>
<noscript id="muffinRecipeDetails">
<h3>Muffiny z mąki gryczanej i kukurydzianej</h3>
<ul style="display: inline-block; text-align:left; color: #000;">
<li>mąka gryczana - 120 gram</li>
<li>mąka kukurydziana - 80 gram</li>
<li>skórka cytrynowa</li>
<li>sok z połowy cytryny</li>
<li>olej - 100 ml</li>
<li>mleko - 100 ml</li>
<li>jajka - 2 sztuki</li>
<li>Rozbij jajka z mlekiem</li>
<li>Wlej mieszankę do mąki i zmiksuj</li>
<li>Wlej ciasto do papilotek</li>
<li>Piecz aż będą złote i popękane</li>
</ul>
</noscript>
<!-- HTML -->
Użyj wyobraźni lub kliknij
Zdjęcie Jan Szwagrzyk na Unsplash
HTML, CSS, Javascript
<style>
.u-CourtainLeftSlowImg:hover {
cursor: zoom-in;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var backgroundCanvas = document.createElement("div");
backgroundCanvas.style.cssText = "position: fixed; top: 0; left: 100%; width: 0; height: 100%; z-index: 1; background: rgba(0,0,0,0.9) none center/auto 100vmin no-repeat; transition: all 6s ease-out; cursor: zoom-out;";
document.body.appendChild(backgroundCanvas);
backgroundCanvas.onclick = function() {
backgroundCanvas.style.top = "0";
backgroundCanvas.style.left = "100%";
backgroundCanvas.style.width = "0";
backgroundCanvas.style.height = "100%";
};
var zoomInImgLinks = document.getElementsByClassName("u-CourtainLeftSlowImg");
for(var i=0; i<zoomInImgLinks.length; ++i) zoomInImgLinks[i].addEventListener("click", function(e) {
e.preventDefault();
backgroundCanvas.style.backgroundImage = "url('"+e.target.parentNode.href+"')";
backgroundCanvas.style.top = "0";
backgroundCanvas.style.left = "0";
backgroundCanvas.style.width = "100%";
backgroundCanvas.style.height = "100%";
})
})
</script>
<!-- HTML -->
<a class="u-CourtainLeftSlowImg" href="img/jan-szwagrzyk-0YbvWz-Wxqw-unsplash.jpg">
<img src="img/jan-szwagrzyk-0YbvWz-Wxqw-unsplash-min.jpg" width="400" height="495" alt="Dziewczyna w czarnych pończochach">
</a>
<!-- HTML -->